DEV Community

Cover image for Advance Add Tags input with REACT JS
Krushna Chandra Dash
Krushna Chandra Dash

Posted on

Advance Add Tags input with REACT JS

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

No time to ready then here is the CodeSandbox link.

CodeSandbox DEMO
CodeSandbox Code Example

Step-1

Create A react js project.

npx create-react-app my_app
Enter fullscreen mode Exit fullscreen mode

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>
  );
};

Enter fullscreen mode Exit fullscreen mode

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);
  };
Enter fullscreen mode Exit fullscreen mode

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);
  };
Enter fullscreen mode Exit fullscreen mode

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));
  };
Enter fullscreen mode Exit fullscreen mode

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();
  };
Enter fullscreen mode Exit fullscreen mode

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("");
    }
  };
Enter fullscreen mode Exit fullscreen mode

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>
  );
};

Enter fullscreen mode Exit fullscreen mode

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;
}

Enter fullscreen mode Exit fullscreen mode

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

Top comments (0)