Вероятно, вы уже используете формы с Angular2 как с подходами на основе шаблонов, так и на основе FormBuilder. Определение настраиваемых валидаторов со вторым подходом очевидно, поскольку мы можем установить их при определении контрольных групп.
Также можно определить настраиваемые валидаторы для форм на основе шаблонов с помощью директив.
Синхронная проверка
Давайте возьмем образец «необходимого» валидатора, предоставленного Angular2 из коробки. Когда мы добавляем к входным данным атрибут обязательный, валидатор автоматически регистрируется.
У нас есть это «волшебное» поведение, поскольку к этому атрибуту применяется директива RequiredValidator.
Хорошо, директива применяется, но как она добавляется. Вероятно, вы видели атрибут провайдеры в директиве. Валидатор определяется на этом уровне записью NG_VALIDATORS для поставщика. Когда Angular2 инициализирует проверку ввода, он будет просматривать все зарегистрированные валидаторы для этого токена для текущего элемента.
Провайдер может соответствовать функции валидатора (как показано ниже) или классу директив (как описано ниже). В этом случае мы используем атрибут useValue для возврата функции проверки.
Директива валидатора может быть немного менее простой и использовать входные атрибуты для настройки валидатора. Это случай директивы MinLengthValidator, предоставляемой фреймворком.
В этом случае нам нужно реализовать класс Validator и его метод validate. Последний просто делегирует функцию проверки (здесь Validators.minLength). Конструктор имеет доступ к значению атрибута minlength с помощью @Attribute, как описано в документации:
Указывает, что следует ввести постоянное значение атрибута. Директива может вводить постоянные строковые литералы атрибутов элемента хоста.
Код этой директивы не так уж и сложен:
Как и RequiredValidator, нам необходимо зарегистрировать его для записи NG_VALIDATORS в провайдерах. В этом случае мы используем атрибут useExisting с функцией forwardRef. Последнее требуется из-за циклической зависимости и из-за того, что подъем не поддерживается для классов.
Асинхронная проверка
Этот подход также поддерживается для асинхронных валидаторов. В этом случае нам нужно использовать токен NG_ASYNC_VALIDATORS.
Мы можем использовать ту же концепцию, за исключением того, что метод проверки в директиве должен возвращать обещание. Вот простой пример, в котором используется необработанное обещание. Значение ввода проверяется асинхронно через 3 секунды. Если значение равно «test», проверка не выполняется. В противном случае это получится.
Последний шаг состоит в регистрации класса AsyncValidationDirective для записи NG_ASYNC_VALIDATORS в поставщиках.
Образец
Асинхронная проверка: https://plnkr.co/edit/twbx4qpuwQ2qSwiXRSBk?p=preview