Автозаполнение пользовательского интерфейса материала — Отключить список после выбора элемента

#reactjs #material-ui

Вопрос:

Я создаю компонент автозаполнения в React.js с помощью материала-UI безголовый крючок для автозаполнения. Компонент работает должным образом. Когда пользователь попытается ввести какой-либо символ, Listbox он автоматически откроется.

Но проблема в том, что когда пользователь выбирает что-либо и обращает внимание на элемент ввода, ListBox он снова открывается. Как я могу это предотвратить?

Codesandbox:

Редактировать fg56t

Код:

 import React from 'react';
import useAutocomplete from '@material-ui/lab/useAutocomplete';

function AutocompleteComponent(props) {
  const { data } = props;

  const [value, setValue] = React.useState('');
  const [isOpen, setIsOpen] = React.useState(false);

  const handleOpen = function () {
    if (value.length > 0) {
      setIsOpen(true);
    }
  };

  const handleInputChange = function (event, newInputValue) {
    setValue(newInputValue);
    if (newInputValue.length > 0) {
      setIsOpen(true);
    } else {
      setIsOpen(false);
    }
  };

  const {
    getRootProps,
    getInputProps,
    getListboxProps,
    getOptionProps,
    groupedOptions
  } = useAutocomplete({
    id: 'form-control',
    options: data,
    autoComplete: true,
    open: isOpen, // Manually control
    onOpen: handleOpen, // Manually control
    onClose: () => setIsOpen(false), // Manually control
    inputValue: value, // Manually control
    onInputChange: handleInputChange, // Manually control
    getOptionLabel: (option) => option.name
  });

  const listItem = {
    className: 'form-control__item'
  };

  return (
    <div className="app">
      <div className="form">
        <div {...getRootProps()}>
          <input
            type="text"
            className="form-control"
            placeholder="Location"
            {...getInputProps()}
          />
        </div>
        {groupedOptions.length > 0 amp;amp; (
          <ul
            className="form-control__box"
            aria-labelledby="autocompleteMenu"
            {...getListboxProps()}
          >
            {groupedOptions.map((option, index) => {
              return (
                <li {...getOptionProps({ option, index })} {...listItem}>
                  <div>{option.name}</div>
                </li>
              );
            })}
          </ul>
        )}
      </div>
    </div>
  );
}

export default AutocompleteComponent;
 

Комментарии:

1. Я только что обновил ваш код в песочнице . Пожалуйста, ознакомьтесь. Как только пользователь выбирает какое-либо значение, мы просто отключаем ввод, используя приведенный ниже код. disabled={Boolean(value) amp;amp; !isOpen} Хотя это отключает возможность повторного редактирования выбора после того, как пользователь выбрал какое-либо значение.

2. @Junaid Автозаполнение не должно отключаться, пользователь может повторно ввести любые результаты совпадения.

Ответ №1:

Вы можете сохранить выбранный элемент в состоянии и использовать его в handleOpen, чтобы решить, должен ли отображаться список. Для настройки SelectedItem вы можете изменить щелчок по умолчанию, предоставляемый getOptionProps

 import React from 'react';
import useAutocomplete from '@material-ui/lab/useAutocomplete';

function AutocompleteComponent(props) {
  const { data } = props;

  const [value, setValue] = React.useState('');
  const [isOpen, setIsOpen] = React.useState(false);
  const [selectedItem, setSelectedItem] = React.useState('');

  const handleOpen = function () {
    if (value.length > 0 amp;amp; selectedItem !== value) {
      setIsOpen(true);
    }
  };

  const handleInputChange = function (event, newInputValue) {
    setValue(newInputValue);
    if (newInputValue.length > 0) {
      setIsOpen(true);
    } else {
      setIsOpen(false);
    }
  };

  const {
    getRootProps,
    getInputProps,
    getListboxProps,
    getOptionProps,
    groupedOptions
  } = useAutocomplete({
    id: 'form-control',
    options: data,
    autoComplete: true,
    open: isOpen, // Manually control
    onOpen: handleOpen, // Manually control
    onClose: () => setIsOpen(false), // Manually control
    inputValue: value, // Manually control
    onInputChange: handleInputChange, // Manually control
    getOptionLabel: (option) => option.name
  });

  const listItem = {
    className: 'form-control__item'
  };

  return (
    <div className="app">
      <div className="form">
        <div {...getRootProps()}>
          <input
            type="text"
            className="form-control"
            placeholder="Location"
            {...getInputProps()}
          />
        </div>
        {groupedOptions.length > 0 amp;amp; (
          <ul
            className="form-control__box"
            aria-labelledby="autocompleteMenu"
            {...getListboxProps()}
          >
            {groupedOptions.map((option, index) => {
              return (
                <li
                  {...getOptionProps({ option, index })}
                  {...listItem}
                  onClick={(ev) => {
                    setSelectedItem(option.name);
                    getOptionProps({ option, index }).onClick(ev);
                  }}
                >
                  <div>{option.name}</div>
                </li>
              );
            })}
          </ul>
        )}
      </div>
    </div>
  );
}

export default AutocompleteComponent;

 

Отредактированный

Ответ №2:

Вы можете изменить реквизиты, переданные в поле ввода, перед их применением. Таким образом, вы можете удалить событие, которое происходит при нажатии на ввод.

 var newProps = getInputProps();

delete newProps.onMouseDown; //delete the extra MouseDown event

return (
...
    <input
    ...
     
    placeholder="Location"
    {...newProps}  //use newProps rather than calling getInputProps
 

И он перестанет показывать это всплывающее окно, когда вы нажмете на него.

Вы можете проверить рабочий код здесь