Отображение количества совпадающих параметров поиска при вводе текстового поля в автозаполнении пользовательского интерфейса Material

#reactjs #material-ui

#reactjs #материал-пользовательский интерфейс

Вопрос:

Я пытаюсь настроить автозаполнение пользовательского интерфейса Material и показать количество параметров, которые в настоящее время отображаются в всплывающем меню после того, как пользователь выполнит поиск и введет строку в поле поиска (это до того, как вы выберете опцию, и она станет value , которую легко подсчитать value.length ). Возможно, мне не хватает реквизита, чтобы получить количество отображаемых опций из всего массива опций, когда пользователь вводит нажатие клавиши в <Textfield/> renderInput реквизите в <Autocomplete/> .

Вот код:

  <Autocomplete
        value={value}
        onClose={handleClose}
        onChange={(event, newValue) => {
          setValue(newValue);
        }}
        options={options}
        getOptionLabel={option => option.title}
        renderInput={params => (
          <React.Fragment>
            <TextField
              {...params}
              variant="underlined"
              placeholder="Search"
            />
            <span className={classes.visibleFilterNum}>
              Showing X of {options.length}
            </span>
          </React.Fragment>
        )}
      />
  

Пока что это компонент, необходимо постоянно обновлять счетчик для отображения X от общего количества опций

изображение WIP

Вот код чего-то подобного, извлеченный из документов Material UI example docs для лучшего примера начального набора кода

Ответ №1:

Использовать useAutocomplete хук просто, поскольку он предоставляет groupedOptions переменную (которая является отфильтрованными параметрами).

Вот пример:

 export default function UseAutocomplete() {
  const classes = useStyles();
  const {
    getRootProps,
    getInputLabelProps,
    getInputProps,
    getListboxProps,
    getOptionProps,
    groupedOptions
  } = useAutocomplete({
    id: "use-autocomplete-demo",
    options: top100Films,
    getOptionLabel: (option) => option.title
  });

  return (
    <div>
      <div {...getRootProps()}>
        <label className={classes.label} {...getInputLabelProps()}>
          useAutocomplete
        </label>
        <input className={classes.input} {...getInputProps()} />
      </div>
      {groupedOptions.length > 0 ? (
        <>
          <div>
            Showing {groupedOptions.length} of {top100Films.length}
          </div>
          <ul className={classes.listbox} {...getListboxProps()}>
            {groupedOptions.map((option, index) => (
              <li {...getOptionProps({ option, index })}>{option.title}</li>
            ))}
          </ul>
        </>
      ) : null}
    </div>
  );
}
  

Редактировать хук useAutocomplete


groupedOptions компонент не предоставляет никаких прямых возможностей Autocomplete , но можно определить количество отображаемых параметров, проверив HTML для подсчета параметров после его отображения. В приведенном ниже примере это делается путем переопределения компонента Paper . Параметры отображаются внутри Paper элемента, и все параметры получают атрибут data-option-index. В приведенном ниже примере эти аспекты используются для подсчета параметров, используемых querySelectorAll в Paper элементе:

 import React from "react";
import TextField from "@material-ui/core/TextField";
import Autocomplete from "@material-ui/lab/Autocomplete";
import Paper from "@material-ui/core/Paper";

const NumResultsHeader = ({ children, ...other }) => {
  const headerRef = React.useRef();
  const countRef = React.useRef();
  const paperRef = React.useRef();
  React.useEffect(() => {
    const numOptions = paperRef.current.querySelectorAll(
      "li[data-option-index]"
    ).length;
    countRef.current.innerHTML = numOptions;
    if (numOptions > 0) {
      headerRef.current.style.display = "block";
    } else {
      headerRef.current.style.display = "none";
    }
  });
  return (
    <>
      <div ref={headerRef} style={{ display: "none" }}>
        Showing <span ref={countRef}></span> of {top100Films.length}
      </div>
      <Paper {...other} ref={paperRef}>
        {children}
      </Paper>
    </>
  );
};
export default function ComboBox() {
  return (
    <Autocomplete
      id="combo-box-demo"
      options={top100Films}
      getOptionLabel={(option) => option.title}
      style={{ width: 300 }}
      PaperComponent={NumResultsHeader}
      renderInput={(params) => (
        <TextField {...params} label="Combo box" variant="outlined" />
      )}
    />
  );
}
  

Редактирование автозаполнения отображение количества отфильтрованных параметров

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

1. это потрясающее решение и удивительно подробное объяснение того, как этого добиться! спасибо, Райан 🙂

2. как я могу получить доступ к top100Films / количеству параметров для отображения в <span>Showing {countRef} of {top100Films.length}</span> , если массив top100Films не определен в том же файле, где мы создаем NumResultsHeader ? Я пытался передать, но у меня появляется length = undefined

3. @user10782250 Я рекомендую вам создать новый вопрос с изолированной средой кода, воспроизводящей проблему, с которой вы столкнулись.

4. Ах, спасибо! вот codesandbox проблемы, связанной с отделением массива параметров от ComboBox файла / компонентов. В приведенном здесь примере: codesandbox.io/s /… , я импортирую ComboBox в свой App.js файл и передаю параметры через props.

5. @user10782250 В настоящее время нет хорошего способа справиться с этим, но я зарегистрировал проблему по этому поводу: github.com/mui-org/material-ui/issues/23043 . Я думаю, вполне вероятно, что v5 каким-то образом будет поддерживать это, но до стабильного выпуска еще несколько месяцев.