Home > Enterprise >  How to add a CSS class based on a condition
How to add a CSS class based on a condition

Time:09-07

I am trying to add a class for chips based on whether the values are valid or not. like this

enter image description here

For that added a flag variable to check whether the email is valid or not.

className={flag ? "chip-tag-error": "chip-tag"}

but there is no change in result instead invalid emails are added

import React, { useRef, useState } from "react";
import ReactDOM from "react-dom";
import Chip from "@material-ui/core/Chip";
import TextField from "@material-ui/core/TextField";
import './styles.css';


export const TagActions = () => {
    const [items, setItem] = useState<string[]>([]);
    const [value, setValue] = useState('')
    const [error, setError]= useState('')
    const divRef = useRef<HTMLDivElement>(null)
    const [flag, setFlag] = useState(false)

    const handleDelete = (item:any) => {
        console.log("handleDelete", item)
        const result = items.filter(i => i !== item)
        setItem(result)
      };
    
    const handleItemEdit = (item:any) =>{
        console.log("handleItemEdit", item)
        const result = items.filter(i => i !== item)
        setItem(result)
        setValue(item)
        console.log("value", value)
        
    };

    const handleKeyDown = (evt:any) => {
        if (["Enter", "Tab", ","].includes(evt.key)) {
          evt.preventDefault();

          var test = value.trim();
    
          if (test && isValid(test)) {
            items.push(test)
            setValue("")
           
          }
        }
    };

    const isValid = (email:any)=> {
        let error = null;
    
        if (isInList(email)) {
          error = `${email} has already been added.`;
        }
    
        if (!isEmail(email)) {
          setFlag(true)
          error = `${email} is not a valid email address.`;
        }
        
        if (error) {
            setError(error);
    
          return false;
        }
    
        return true;
    }

    const isInList = (email:any)=> {
        return items.includes(email);
      }
    
    const isEmail = (email:any)=> {
        return /[\w\d\.-] @[\w\d\.-] \.[\w\d\.-] /.test(email);
    }

    const handleChange = (evt:any) => {
        setValue(evt.target.value)
        // setError("")
        
    };

    const handlePaste = (evt:any) => {
        evt.preventDefault();
    
        var paste = evt.clipboardData.getData("text");
        var emails = paste.match(/[\w\d\.-] @[\w\d\.-] \.[\w\d\.-] /g);
    
        if (emails) {
          var toBeAdded = emails.filter((email:any) => !isInList(email));
            
            setItem(toBeAdded)
        
        }
    };
    


    return (
        <>
          <div>
          <TextField id="outlined-basic" variant="outlined"
          InputProps={{
            startAdornment: items.map(item => (
              <Chip
                className={flag ? "chip-tag-error": "chip-tag"}
                key={item}
                tabIndex={-1}
                label={item}
                onDelete={() => handleDelete(item)}
                onClick={() => handleItemEdit(item)}
              />
            )),
  
          }}
            ref={divRef}
            value={value}
            placeholder="Type or paste email addresses and press `Enter`..."
            onKeyDown={(e) => handleKeyDown(e)}
            onChange={(e) => handleChange(e)}
            onPaste={(e) => handlePaste(e)}
          />
          </div>
  
          {error && <p className="error">{error}</p>}
        </>
      );
}

Styles.css


.chip-tag-error{
    color:red;
}
.chip-tag{
    color:blue;
}

Please give me a solution to fix this problem.

CodePudding user response:

Hey try adding it like this:

className={`${flag ? "chip-tag-error": "chip-tag"}`}

CodePudding user response:

This is a scoping problem.

If we look at this piece of your code you see that you have one value of flag for all items in the map. So you would have all items either valid or invalid.

          InputProps={{
            startAdornment: items.map(item => (
              <Chip
                className={flag ? "chip-tag-error": "chip-tag"}
                key={item}
                tabIndex={-1}
                label={item}
                onDelete={() => handleDelete(item)}
                onClick={() => handleItemEdit(item)}
              />
            )),
  
          }}

What you need to do is compute the value of flag inside the map rather that on the whole set of items.

      InputProps={{
        startAdornment: items.map(item => (
          <Chip
            className={!isEmail(item) ? "chip-tag-error": "chip-tag"}
            key={item}
            tabIndex={-1}
            label={item}
            onDelete={() => handleDelete(item)}
            onClick={() => handleItemEdit(item)}
          />
        )),

      }}

Two other notes:
 * It's always better to use strict typing on functions rather than use `any`
 * You have similar problems with your error states
  • Related