Реактивные формы — это одна из лучших вещей в Angular. Поскольку они упрощают работу с большими и действительно динамичными формами. В этой мы рассмотрим создание кастомного элемента формы.
Могут быть разные причины для создания собственных элементов управления формой.
formControl
, который использовали бы во многих компонентах приложения.Но, прежде чем мы начнем создавать пользовательский элемент управления формой, давайте определим какими свойствами и поведением он должен обладать:
В этом примере мы рассмотрим создание достаточно простого компонента для выбора одного значения из списка возможных.
Для этих целей мы могли бы использовать элемент select
. И, в большинстве случаев, я советовал бы Вам использовать именно его. Но мы хотим рассмотреть как можно создавать собственные элементы форм и такой компонент отлично подходит для этой тривиальной задачи. Кроме того, может быть достаточно много причин, почему нам необходим кастомный элемент для выбора значения.
Итак, давайте начнем с создания компонента CustomSelectComponent
, который принимает из родительского компонента массив options
и отображает его в шаблоне. Также у нас есть метод OptionsSelect
, который сохранят выбранное пользователем значение в свойство innerValue
.
Этот компонент работает хорошо и мы уже можем использовать его в шаблоне формы, как только задекларируем его в модуле нашего приложения.
Однако, этот компонент никак не связан с нашей формой, а нам необходимо, чтобы он умел работать с реактивными (и не только) формами, передавал выбранное значение в модель и т.д.
Иными словами — нам нужна возможность использовать form api директивы, например formControl
:
Хорошо, но как мы можем сделать из обычного компонента компонент типа formControl
? Для этого нам нужно узнать что такое ControlValueAccessor
, потому что это именно то, что использует Angular для построения коммуникаций между моделью формы и DOM элементом.
Компонент может опционально реализовывать интерфейс ControlValueAccessor
, который позволяет записывать значение в компонент и прослушивать его изменения. Этот интерфейс используется в директивах NgModel
и FormControlName
.
В кастомных элементах формы мы должны добавить собственную реализацию этого интерфейса.
Интерфейс ControlValueAccessor
выглядит следующим образом:
Итак, давайте перепишем наш компонент и реализуем в нем методы описанные выше:
Здесь мы регистрируем обработчики событий, а также в методе writeValue
:
selectedOption;
Вызов же метода writeValue
происходит в методе optionSelect
, который используется в качестве обработчика клика на элементе списка. Также в этом методе вызывается функция onTouched и изменяется свойство open для того, чтобы убрать выпадающий список.
CustomSelectComponent
почти готов к использованию. Но хотя мы и реализовали все необходимые методы интерфейса ControlValueAccessor
, Angular все еще не воспринимает его как таковой, потому что его необходимо зарегистрировать.
Для регистрации аксессора используется мультипровайдер с токеном NG_VALUE_ACCESSOR
. Его следует добавить в список провайдеров нашего компонента:
Здесь мы сообщаем этому токену о нашем компоненте. Также, следует обратить внимание на использование forwardRef
. Это необходимо, поскольку класс нашего компонента еще не будет определен, когда провайдер будет зарегистрирован и нам нужно сообщить конструктору провайдера о том, что необходимо дождаться определения класса.
После того, как мы создали нашу модель формы, мы можем связать наш кастомный form Control с моделью с помощью директивы formControlName
или formControl
.
Мы же хотим модифицировать форму из предыдущей статьи и изменить элемент для выбора типа контакта, поэтому в нашем случае мы просто заменили тег select
на custom-select
.
Однако, использование кастомного элемента формы не ограничено только модель-ориентированными формами. Его также можно использовать и в шаблон-ориентированных формах — просто использовать синтаксис двухсторонней привязки данных:
На этом все. Надеюсь этот материал был полезен для Вас.
Шпаргалка по Angular. Angular — JavaScript-фреймворк с открытым исходным кодом. Предназначен для разработки одностраничных (SPA) приложений. Его цель — расширение браузерных приложений на основе MVC-шаблона, а также упрощение тестирования и разработки.
В данном руководстве пойдет речь о селекторе, Databinding, интерполяции, связывание свойств и многом другом.
Использование класса Subject для создания сервиса, реализующего observable и observer в Angular