Thamali Wijewardhana
Thamali Wijewardhana

Reputation: 512

Reactjs : give text input to select element(combo box)

I am trying to implement a react js select element. I am giving a set of options to that element such that the user can select. In addition to that I need to add a place holder to that element and make it able to type values and enter as in a text box. Then the users can either enter custom values to it or select an element from the drop down.

Below is the code snippet I used for implementing the select element. But it only allows selecting. Can anyone help me to implement a select element which allows inputting text and place holder.

<select className="form-control form-control-sm" ref="LayerL6Select" name="LayerL6Select"  id="LayerL6Select">
<option value="1">Apple</option>    
<option value="2">Mango</option>
</select>

Upvotes: 2

Views: 5717

Answers (3)

Rabah Ali Shah
Rabah Ali Shah

Reputation: 71

If I am not wrong, You want an a select field that should also take input text which can be searched over the options. If yes, then you can use a library called 'react-select'

There is a property in this component namely 'isSearchable' which is Boolean type.

Below is the component which I have created for my project. You can modify it according to your requirements.

import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import ReactSelect, { components } from 'react-select';

import Icon from '../Icon';

import './Select.css';

const MultiValue = props => {
  const values = props.selectProps.value;
  const lastValue = values[values.length - 1];
  let label = props.data.label;
  if (lastValue.label !== label) {
    label += ', ';
  }

  return <span>{label}</span>;
};

const Option = props => {
  return (
    <components.Option {...props}>
      <div className="flex items-center">
        <div className="h-2 w-2">
          {props.isSelected ? (
            <Icon name={'checkbox-active'} />
          ) : (
            <Icon name={'checkbox-default'} />
          )}
        </div>
        <label
          id={props.data.value}
          className="ml-3 mt-1"
        >
          <span>{props.value}</span>
        </label>
      </div>
    </components.Option>
  );
};

const Select = ({
  id,
  className = '',
  closeMenuOnSelect = true,
  hideSelectedOptions = false,
  isClearable = true,
  isDisabled = false,
  isMulti = false,
  isSearchable = true,
  onChange,
  options,
  placeholder,
  noIcons = false,
  menuPlacement = 'auto',
  components = {},
  value = [],
}) => {
  const _noIconComponents = {
    DropdownIndicator: () => null,
    IndicatorSeparator: () => null,
  };
  let _components = isMulti ? { Option, MultiValue } : {};
  _components = noIcons
    ? { ..._components, ..._noIconComponents }
    : { ..._components, ...components };

  const selectedOptions = [];

  // Map array of values to an array of selected options
  if (value && Array.isArray(value)) {
    value.forEach(val => {
      const found = options.find(opt => opt.value === val);
      if (found) {
        selectedOptions.push(JSON.parse(JSON.stringify(found)));
      }
    });
  }

  return (
    <ReactSelect
      inputId={`input-${id}`}
      className={classnames(className, 'ohif-select customSelect__wrapper flex flex-1 flex-col')}
      data-cy={`input-${id}`}
      classNamePrefix="customSelect"
      isDisabled={isDisabled}
      isClearable={isClearable}
      isMulti={isMulti}
      isSearchable={isSearchable}
      menuPlacement={menuPlacement}
      closeMenuOnSelect={closeMenuOnSelect}
      hideSelectedOptions={hideSelectedOptions}
      components={_components}
      placeholder={placeholder}
      options={options}
      blurInputOnSelect={true}
      menuPortalTarget={document.body}
      styles={{
        menuPortal: base => ({ ...base, zIndex: 9999 }),
      }}
      value={value && Array.isArray(value) ? selectedOptions : value}
      onChange={(selectedOptions, { action }) => {
        const newSelection = !selectedOptions.length
          ? selectedOptions
          : selectedOptions.reduce((acc, curr) => acc.concat([curr.value]), []);
        onChange(newSelection, action);
      }}
    />
  );
};

Select.propTypes = {
  className: PropTypes.string,
  closeMenuOnSelect: PropTypes.bool,
  hideSelectedOptions: PropTypes.bool,
  isClearable: PropTypes.bool,
  isDisabled: PropTypes.bool,
  isMulti: PropTypes.bool,
  isSearchable: PropTypes.bool,
  noIcons: PropTypes.bool,
  menuPlacement: PropTypes.oneOf(['auto', 'bottom', 'top']),
  onChange: PropTypes.func.isRequired,
  options: PropTypes.arrayOf(
    PropTypes.shape({
      value: PropTypes.string,
      label: PropTypes.string,
    })
  ),
  placeholder: PropTypes.string,
  value: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.string), PropTypes.any]),
};

export default Select;

Upvotes: 0

Maheer Ali
Maheer Ali

Reputation: 36594

You should use <input> followed by <datalist>.Here is example in html you can convert in into react. Note that id attribute of <datalist> should be added list attribute of the <input>

According to DOCS

The datalist element is hooked up to an input element using the list attribute on the input element

<input placeholder="myplaceholder" list="opts"/>
<datalist id="opts">
<option>One</option>
<option>Two</option>
<option>Three</option>
</datalist>

Upvotes: 5

Boobalan
Boobalan

Reputation: 865

If you looking for short time solution. I would suggest following react-select library which helps you to achieve what you want.

https://react-select.com/home

else if you ask this for your personal learning here its source code, you could learn from it source code.

https://github.com/JedWatson/react-select

Upvotes: 2

Related Questions