DEV Community

Cover image for Custom multi select with input field in React js?
Md. Khalid Hossen
Md. Khalid Hossen

Posted on

Custom multi select with input field in React js?

*Here, I make customs multi select input *

In general Working Procedure:

  1. Enter value and open drop down content with match value
  2. then click suggest box and store country into geography state
  3. after store geography make toggleSuggestBox false
  4. you can also remove country using cross sign.
   const [geography, setGeography] = useState([]);
   const [toggleSuggestBox, setToggleSuggestBox] = useState(false);
   const [geographyText, setGeographyText] = useState('');

 // open search text wise drop down content (suggest box ) 
 const geographyChangeHandler = (e) => {

        setGeographyText(e.target.value);
        setToggleSuggestBox(true);

        //here countries is fake json where i put all the country name as label
        const filterCountry = Countries?.filter((item) => item.label.toLowerCase().includes(e.target.value.toLowerCase( 
        )));
        setGeographySuggest(filterCountry);
    }

    // add geography using suggest click
    const handleSuggestClick = (item) => {
        setGeographyText('')
        setGeography([...geography, item]);
        setGeographySuggest([])
        setToggleSuggestBox(false);

    }

    //remove geography from geography array  
    const removeGeographyHandler = (item) => {
        console.log(item, "click for remove an item");

        const filterData = geography.filter(country => country !== item);
        console.log(filterData, "test filter data ")
        setGeography(filterData);

    }

<div className='geography'>
    <label>Countries Allowed</label>
{/* how to do it manually  */}

    <div className='multi-select-sections'>

          <input name='geography'
                 value={geographyText}
                 type="text"
                 onChange={geographyChangeHandler}
               />

      {geographySuggest.length > 0 && (
            <div className="suggest-box"
              style={{ display: toggleSuggestBox && geographyText.length > 0 ? "flex" : "none" }}>
             <div>{geographySuggest?.slice(0, 10).map((country, index) => (
       <button key={index}                                               className="suggest-box-search-btn"
onClick={() => handleSuggestClick(country.label)}>

     <span className="suggest-box-line-climb">
          {country.label}
     </span>
      </button>
      ))}
 </div>
     </div>
 )}
{
     geography?.map((item, index) => (
      <div key={index} className='single-item'>
               <span className='country-name'>{item}</span>
               <span className='geography-cross' onClick={() => removeGeographyHandler(item)}>x</span>
     </div>
     ))
 }

</div>

</div>

Enter fullscreen mode Exit fullscreen mode

//sass file here

.geography {
    margin: 10px 0;
    position: relative;
    display: flex;
    label {
          width: 120px;
         }
    .multi-select-sections {
           border: $border-color;
           width: 300px;
           min-height: 40px;
           overflow: hidden;
           display: flex;
           align-items: center;
           flex-wrap: wrap;
           gap: 10px;
           padding: 5px;
           .single-item {
              display: flex;
              background: #e6e6e6;
              overflow: hidden;
              align-items: center;
              border-radius: 6px;

              .country-name {
                   font-size: 14px;
                   padding: 0px 5px;
               }

               .geography-cross {
                   font-size: 18px;
                   padding: 2px 5px;
                   cursor: pointer;
                     &:hover {
                       background-color: #ffbdad;
                       color: #de350b;
                       }
                 }
           }
           input {
              padding: 3px;
              width: 100vw;
              height: 28px;
              border: none;
               &:focus {
                  border: 1px solid #0048ba;
                }
               &:hover {
                   border: 1px solid #0048ba;
                }
           }
         .suggest-box {
              position: absolute;
              width: 65%;
              left: 118px;
              top: 26px;
              z-index: 9999999;
              background-color: #fff;
              box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 21%);
              margin-top: 5px;
              border-radius: 3px;
              padding: 15px 20px;
              max-height: 300px;
              overflow-y: auto;
              flex-direction: column;

              .suggest-box-search-btn {
                   width: 100%;
                   display: flex;
                   align-items: center;
                   gap: 10px;
                   height: 40px;
                   outline: none;
                   background: transparent;
                   text-align: left;
                   font-size: 14px;
                   font-family: "Open Sans", sans-serif;
                   border: none;
                   border-bottom: 1px solid #eaeaea;

                      &:hover {
                         color: $primary-color;
                         transition: 0.5s;
                 }
                  .suggest-box-line-climb {
                         display: -webkit-box;
                        -webkit-line-clamp: 1;
                        -webkit-box-orient: vertical;
                        overflow: hidden;
                    }
                }
          }
      }
}

Enter fullscreen mode Exit fullscreen mode

Top comments (0)