I am trying to add a class for chips based on whether the values are valid or not. like this
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