Advance Add Tags input with REACT JS
Tags: react, javascript, typescript, webdev
Published: 2023-08-13 17:25:08

Hi guys. In this article we will create a advance multiple tags input using React.JS and a bit of CSS.

Where user can 

1. **_Add tag by entering comma(,) ._**
2. **_Add tag by pressing "Enter" key._**
3. **_Edit last tag by entering "Back Space"._**
4. **_On Blur add input text to Tag list._**



![Advance Add Tags input with REACT JS](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/njpq8vsaudej9d6qgold.JPG)

## **No time to ready then here is the `CodeSandbox` link.**
`CodeSandbox` [DEMO](https://8xjvmz.csb.app/)
`CodeSandbox` [Code Example](https://codesandbox.io/s/adavncetagsinput-8xjvmz)


## **Step-1**
Create A react js project.

```
npx create-react-app my_app
```
## **Step-2**
Then lets create a component name of **AdavnceTagsInput.js**.
and the code with logic whick will look like below

```
import React, { useState, useRef } from "react";
import "./AdavnceTagsInput.css";

export const AdavnceTagsInput = () => {
  // to store input field data
  const [tagText, setTagText] = useState("");

  // to store tags data in array form
  const [tags, setTags] = useState([]);

  // to handle focus or blur state of input field
  const [isKeyReleased, setIsKeyReleased] = React.useState(false);
  const inputRef = useRef(null);

  const onChange = (e) => {
    const { value } = e.target;
    setTagText(value);
  };

  return (
    <div className="CustomTagComp" >
      <div className="selected_tag">
        {tags.map((tag, index) => (
          <div key={index} style={{ display: "flex" }}>
            <span className="selected_tag_text">{tag}</span>
            <button  className="selected_tag_button" >
              &#10005;
            </button>
          </div>
        ))}
        <input
          value={tagText}
          placeholder="Enter Tag"
          className="tags_input"
        />
      </div>
    </div>
  );
};

```

## **Step-3**
Then lets add *onKeyDown* function, where we will check whether input field value is there . And on Enter or using comma(,) we will add value to tag list

```
// handle key down
    const onKeyDown = (e) => {
    const { key } = e;
    const trimmedInput = tagText.trim(); // remove extra space from both side

    // on entering "," add text to tag list
    if (key === "," && trimmedInput.length && !tags.includes(trimmedInput)) {
      e.preventDefault();
      setTags(
        (prevState) =>
          !prevState.includes(trimmedInput) && [...prevState, trimmedInput]
      );
      setTagText("");
    }

    // on press enter add text to tag list
    if (
      key === "Enter" &&
      trimmedInput.length &&
      !tags.includes(trimmedInput)
    ) {
      e.preventDefault();
      setTags(
        (prevState) =>
          !prevState.includes(trimmedInput) && [...prevState, trimmedInput]
      );
      setTagText("");
    }

    // on press back space user can exit last tag list
    if (
      key === "Backspace" &&
      !tagText.length &&
      tags.length &&
      isKeyReleased
    ) {
      const tagsCopy = [...tags];
      const poppedTag = tagsCopy.pop();
      e.preventDefault();
      setTags(tagsCopy);
      setTagText(poppedTag);
    }

    setIsKeyReleased(false);
  };
```

## **Step-4**
Then lets add *onKeyUp* function, where we will make our isKeyReleased false ,means we move out of input field
```
const onKeyUp = () => {
    setIsKeyReleased(true);
  };
```

## **Step-5**
Then lets add *removeTag* function, when user click on remove button in tag, we will remove tag from tag list .
```
const removeTag = (index) => {
    setTags((prevState) => prevState.filter((tag, i) => i !== index));
  };
```

## **Step-6**
Then lets add *handleFocus* function, So when user click on anywhere of input tag box, we will make input field focus .
```
  const handleFocus = (e) => {
    let input = inputRef.current;
    e.stopPropagation();
    if (tags && tags.length > 0) {
      input.classList.remove("d-none");
    }
    input.focus();
  };
```

## **Step-7**
Then lets add *handleBlur* function, When user enter some text and move out of input field without adding value to tag list, then we will add the value to tag list automatically.
```
   const handleBlur = () => {
    setIsKeyReleased(false);
    if (tagText) {
      let trimmedInput = tagText.replace(/,/g, "");
      if (trimmedInput.length && !tags.includes(trimmedInput)) {
        setTags(
          (prevState) =>
            !prevState.includes(trimmedInput) && [...prevState, trimmedInput]
        );
      }
      setTagText("");
    }
  };
```

## **Finally**

So finally our `AdavnceTagsInput.js` will look like this.
```
import React, { useState, useRef } from "react";
import "./AdavnceTagsInput.css";

export const AdavnceTagsInput = () => {
  // to store input field data
  const [tagText, setTagText] = useState("");
  // to store tags data in array form
  const [tags, setTags] = useState([]);
  // to handle focus or blur state of input field
  const [isKeyReleased, setIsKeyReleased] = React.useState(false);
  const inputRef = useRef(null);

  const onChange = (e) => {
    const { value } = e.target;
    setTagText(value);
  };

  // handle key down
  const onKeyDown = (e) => {
    const { key } = e;
    const trimmedInput = tagText.trim(); // remove extra space from both side

    // on entering "," add text to tag list
    if (key === "," && trimmedInput.length && !tags.includes(trimmedInput)) {
      e.preventDefault();
      setTags(
        (prevState) =>
          !prevState.includes(trimmedInput) && [...prevState, trimmedInput]
      );
      setTagText("");
    }

    // on press enter add text to tag list
    if (
      key === "Enter" &&
      trimmedInput.length &&
      !tags.includes(trimmedInput)
    ) {
      e.preventDefault();
      setTags(
        (prevState) =>
          !prevState.includes(trimmedInput) && [...prevState, trimmedInput]
      );
      setTagText("");
    }

    // on press back space user can exit last tag list
    if (
      key === "Backspace" &&
      !tagText.length &&
      tags.length &&
      isKeyReleased
    ) {
      const tagsCopy = [...tags];
      const poppedTag = tagsCopy.pop();
      e.preventDefault();
      setTags(tagsCopy);
      setTagText(poppedTag);
    }

    setIsKeyReleased(false);
  };

  // handle key up
  const onKeyUp = () => {
    setIsKeyReleased(true);
  };

  // handle remove tag from tag list
  const removeTag = (index) => {
    setTags((prevState) => prevState.filter((tag, i) => i !== index));
  };

  // handle focus
  const handleFocus = (e) => {
    let input = inputRef.current;
    e.stopPropagation();
    if (tags && tags.length > 0) {
      input.classList.remove("d-none");
    }
    input.focus();
  };

  // handle blur
  const handleBlur = () => {
    setIsKeyReleased(false);
    if (tagText) {
      let trimmedInput = tagText.replace(/,/g, "");
      if (trimmedInput.length && !tags.includes(trimmedInput)) {
        setTags(
          (prevState) =>
            !prevState.includes(trimmedInput) && [...prevState, trimmedInput]
        );
      }
      setTagText("");
    }
  };

  return (
    <div className="CustomTagComp" onClick={handleFocus}>
      <div className="selected_tag">
        {tags.map((tag, index) => (
          <div key={index} style={{ display: "flex" }}>
            <span className="selected_tag_text">{tag}</span>
            <button
              onClick={() => removeTag(index)}
              className="selected_tag_button"
            >
              &#10005;
            </button>
          </div>
        ))}
        <input
          ref={inputRef}
          value={tagText}
          placeholder="Enter Tag"
          onKeyDown={onKeyDown}
          onBlur={handleBlur}
          onKeyUp={onKeyUp}
          onChange={onChange}
          className="tags_input"
        />
      </div>
    </div>
  );
};

```
## **And at end Add CSS**

So finally our `AdavnceTagsInput.css` will look like this.
```
.selected_tag {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  cursor: text;
  border: 2px solid;
  padding: 4px;
  border-radius: 4px;
  gap: 4px;
}
.selected_tag_text {
  /* font-size: 11px; */
  color: rgb(0, 0, 0);
  padding: 4px;
  background-color: rgb(218, 216, 216);
  border-radius: 4px 0px 0px 4px;
  border: none;
  word-break: break-all;
  cursor: text;
}
.selected_tag_button {
  /* font-size: 9px; */
  border: none;
  background-color: rgb(218, 216, 216);
  padding: 4px;
  border-left: 1px solid #ffffff;
  border-radius: 0px 4px 4px 0px;
  color: rgb(0, 0, 0);
  margin-right: 5px;
  font-weight: bold;
  cursor: pointer;
}
.tags_input {
  box-sizing: border-box;
  width: 0;
  min-width: 30px;
  flex-grow: 1;
  border: 0;
  margin: 0;
  outline: 0;
}
.tag_input:focus-visible {
  outline: none;
}

```


And that's all we have successfully create a tags input using React and Bit of JavaScript.

Found it helpful? Hit like and share with other

Make sure you checkout my other articles