#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 от общего количества опций
Вот код чего-то подобного, извлеченный из документов 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>
);
}
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 = undefined3. @user10782250 Я рекомендую вам создать новый вопрос с изолированной средой кода, воспроизводящей проблему, с которой вы столкнулись.
4. Ах, спасибо! вот codesandbox проблемы, связанной с отделением массива параметров от
ComboBox
файла / компонентов. В приведенном здесь примере: codesandbox.io/s /… , я импортирую ComboBox в свойApp.js
файл и передаю параметры через props.5. @user10782250 В настоящее время нет хорошего способа справиться с этим, но я зарегистрировал проблему по этому поводу: github.com/mui-org/material-ui/issues/23043 . Я думаю, вполне вероятно, что v5 каким-то образом будет поддерживать это, но до стабильного выпуска еще несколько месяцев.