Категории автозаполнения пользовательского интерфейса материала в ReactJS

Я использую автозаполнение MUI и Formik и хотел сгруппировать их по категориям. Если у него нет sub_accounts, то у него не должно быть метки заголовка. Примерно так: https://mui.com/material-ui/react-autocomplete/#grouped

КОДЫ------> НАЖМИТЕ ЗДЕСЬ

Ожидаемый результат в пользовательском интерфейсе выглядит примерно так:

  • Мелкая наличность

  • Наличные в банке - Bank of America

    • Bank of America – единственный владелец
    • Банк Америки - юридическое лицо
  • Наличные

  • CIB - Банк Вьетнама

    • Банк Вьетнама Персональный
    • Проверка счета Банка Вьетнама

Petty Cash, Cash In Bank - Bank of America, Cash и CIB - Bank of Vietnam должны быть выровнены.

Cash In Bank - Bank of America и CIB - Bank of Vietnam нельзя щелкнуть/выбрать — можно выбрать только его sub_accounts, а также Petty Cash и Cash.

КОД

export const CashAccountAutocomplete = ({
  field,
  form: { touched, errors, setFieldValue, values },
  disabled,
  ...props
}) => {
  const [inputValue, setInputValue] = useState("");

  const handleChangeEvent = (_, newValue, reason) => {
    if (reason === "clear") {
      setFieldValue(field.name, { id: "", name: "" });
      return;
    }
    setFieldValue(field.name, newValue);
  };

  const handleInputChange = (_, newInputValue) => {
    setInputValue(newInputValue);
  };

  const extractSubAccounts = (accounts) => {
    if (!Array.isArray(accounts)) {
      console.error("Invalid accounts data. Expected an array.");
      return [];
    }

    return accounts.flatMap(
      ({ id, name, sub_accounts }) =>
        sub_accounts && sub_accounts.length > 0
          ? extractSubAccounts(sub_accounts) // Recursively extract sub-accounts
          : [{ id, name }] // Include the account if it has no sub-accounts
    );
  };

  const filteredData = extractSubAccounts(accounts);

  return (
    <Autocomplete
      {...field}
      disabled = {disabled}
      getOptionLabel = {(option) =>
        typeof option === "string" ? option : option?.name || ""
      }
      renderOption = {(props, option) => {
        return (
          <li {...props} key = {option.id}>
            {option?.name}
          </li>
        );
      }}
      filterOptions = {(x) => x}
      options = {filteredData || []}
      autoComplete
      includeInputInList
      filterSelectedOptions
      noOptionsText = {"No data"}
      onChange = {handleChangeEvent}
      inputValue = {inputValue}
      onInputChange = {handleInputChange}
      renderInput = {(params) => (
        <TextField
          {...params}
          {...props}
          error = {touched[field.name] && errors[field.name] ? true : false}
          helperText = {
            touched[field.name] &&
            errors[field.name] &&
            String(errors[field.name].id)
          }
        />
      )}
      fullWidth
    />
  );
};
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
0
138
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я реализовал решение здесь с помощью хуков. Вам необходимо отсортировать значение свойства optionsAutocomplete после фильтрации.

Где находится часть formik?

Joseph 22.04.2024 19:30

Возможно, я неправильно понял вашу проблему. Насколько я понимаю, ваша проблема заключалась в If it has no sub_accounts, then it shouldn't have a header label. Я сосредоточился на этой части. Я не знаком с formik. Решает ли реализация вашу проблему?

discovrer 22.04.2024 21:14

Не совсем. Вы удалили другие вещи, которые мне были нужны в CodeSandbox. Эту проблему следует решить вместе с этим. Можешь форкнуть мои коды и ящик, так будет проще

Joseph 22.04.2024 21:24

Мелкая наличность, наличные в банке - Bank of America, Cash и CIB - Банк Вьетнама должны быть согласованы

Joseph 23.04.2024 01:06
Ответ принят как подходящий

Обновите вспомогательную функцию extractSubAccounts, чтобы установить свойство isHeader только для элементов, которые будут заголовками, а затем также установите свойство isSelectable, если нет параметров подмассива.

const extractSubAccounts = (accounts) => {
  if (!Array.isArray(accounts)) {
    console.error("Invalid accounts data. Expected an array.");
    return [];
  }

  return accounts.flatMap(({ name, sub_accounts, ...account }) => [
    {
      ...account,
      name,
      isHeader: true,
      isSelectable: !sub_accounts?.length,
    },
    ...sub_accounts,
  ]);
};

Обновите обратный вызов renderOptions, чтобы проверить свойства inHeader и isSelectable каждого элемента списка. Идея состоит в том, что элементы списка, которые являются заголовками, а также параметрами, должны быть доступны для выбора и получать классы "MuiAutocomplete-option" CSS, а затем также условно отменить отступы, которые имеют параметры, чтобы заголовки оставаться выровненными.

renderOption = {(props, option) => {
  return (
    <li
      key = {option.id}
      {...(!option.isHeader || option.isSelectable ? props : {})}
      style = {{
        paddingLeft:
          option.isHeader || option.isSelectable ? "1rem" : "2rem",
      }}
    >
      {option.isHeader && !option.isSelectable
        ? <strong>{option.name}</strong>
        : option.name}
    </li>
  );
}}

@Джозеф Ах, упс, его все еще можно было выбрать, потому что реквизиты с обработчиками были безоговорочно распространены на все заголовки. Обновленный ответ. Если вы хотите, чтобы заголовки имели небольшое отступы, вы можете установить это в реквизите style или реализовать фактически стилизованные компоненты, чтобы переопределить и установить желаемые отступы.

Drew Reese 23.04.2024 03:52

@Джозеф Сколько отступов тебе нужно/нужно? Только заголовки или все должно быть одинаково?

Drew Reese 23.04.2024 04:09

@Joseph Похоже, что значение отступа слева по умолчанию составляло около 1rem или 16 пикселей. Вы можете сделать отступ для опций еще на 1рем. Если вы просто хотите, чтобы они все выстроились в ряд, просто используйте style = {{ paddingLeft: "1rem" }}.

Drew Reese 23.04.2024 05:32

Другие вопросы по теме