/datalist-example

Пример реализации datalist

Primary LanguageTypeScript

Реализация datalist.

Первая итерация: Реализация базовой функциональности.

Вход - список рекомендуемых значений, выход - результат ввода. Значения предлагаются по вхождению подстроки.

Компонент будет состоять из двух составляющих: input и dropdown.

Описание компонента:

Поле Значение
@Input items: Array<string> Входной список строк.
@Output onChange: EventEmitter<string> Аутпут результата.
filteredItems: Array<string> Массив строк, фильтрующийся при изменении инпута в шаблоне, отображается в дропдауне.
constructor(private elementRef: ElementRef) Конструктор с инжектом elementRef для обработки «внешнего» клика.
@HostListener(document:click) onBlur Обработчик внешнего клика, если таргет не из datalist-компонента — вызываем closeDropdown.
ngOnChanges({items}: {items: SimpleChange}) Ресетит filteredItems = items, сбрасывает displayedValue.
displayedValue: string Значение отображаемое в инпуте.
isOpen: boolean Состояние дропдауна
onInput(event: Event): void Обработчик изменений инпута, достает из ивента значение инпута и вызывает setValue.
onSelect(value: string): void Обработчик выбора элемента в дропдауне, вызывает setValue(value) и closeDropdown().
setValue(value: string): void Метод установки значения. Сеттит displayValue, фильтрует items по value и сеттит filteredItems, эмиттит значение.
openDropdown(): void Открывает дропдаун, т.е сеттит isOpen = true.
closeDropdown(): void Закрывает дропдаун, т.е сеттит isOpen = false.

Вторая итерация: Поддержка «сложных» типов для @Input() Items

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

Поле Значение
@Input() valueAccessor: { getValue(item):string } Объект с методом, позволяющим достать значение для отображение в инпуте и дропдауне. Дефолтным значением можно задать объект с методом, который просто возвращает item, так мы сделаем этот инпут опциональным.

Третья итерация: Имплементим ControlValueAccessor для поддержки форм ангуляра.

P.S Улучшательства

  • Обработчик «внешнего» клика можно вынести в директиву.

  • Можно сделать datalist компонентом-агностиком, передав в него компонент выступающий в качестве элемента списка. (ngComponentOutlet и тд)