Angular предлагает расширенный набор встроенных элементов управления формами для создания динамических и интерактивных форм. Однако бывают случаи, когда эти элементы управления не соответствуют определенным требованиям или предпочтениям дизайна. Вот где пригодится возможность создавать собственные элементы управления формой в Angular 🙌.

Пользовательский элемент управления формой

Чтобы создать собственный элемент управления формой в Angular, вы можете выполнить следующие шаги 👇

1. Создайте компонент для пользовательского элемента управления формы.

$ ng generate component custom-input

2. В файле TypeScript компонента реализуйте интерфейс ControlValueAccessor.

import { Component } from '@angular/core'
import { ControlValueAccessor } from '@angular/forms'

@Component({
  selector: 'app-custom-input',
  templateUrl: './custom-input.component.html',
  styleUrls: ['./custom-input.component.css']
})
export class CustomInputComponent implements ControlValueAccessor {}

3. Предоставьте токен NG_VALUE_ACCESSOR и настройте его на использование функции forwardRef для ссылки на ваш пользовательский элемент управления.

import { Component, forwardRef } from '@angular/core'
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'

@Component({
  selector: 'app-custom-input',
  templateUrl: './custom-input.component.html',
  styleUrls: ['./custom-input.component.css'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CustomInputComponent),
      multi: true
    }
  ]
})
export class CustomInputComponent implements ControlValueAccessor {}

4. Реализуйте методы ControlValueAccessor.

  • writeValue(obj: any): void — обновляет значение элемента управления формы на основе предоставленного параметра value.
  • registerOnChange(fn: any): void — регистрирует функцию обратного вызова, которая будет вызываться при изменении значения элемента управления формы.
  • registerOnTouched(fn: any): void — регистрирует функцию обратного вызова, которая будет вызываться при касании элемента управления формы.
  • setDisabledState(isDisabled: boolean): void — устанавливает отключенное состояние элемента управления формы на основе предоставленного логического параметра.
@Component(...)
export class CustomInputComponent implements ControlValueAccessor {
  value: string;
  disabled = false;
  onChange: any = (value: any) => {};
  onTouched: any = () => {};

  writeValue(obj: any): void {
    this.value = obj;
  }

  registerOnChange(fn: any): void {
    this.onChange = fn;
  }

  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }

  setDisabledState(isDisabled: boolean): void {
    this.disabled = isDisabled;
  }
}

5. Создайте шаблон для пользовательского элемента управления формы:

  • В шаблон добавьте селектор для вашего пользовательского компонента управления.
  • Привяжите элемент управления к форме с помощью директив ngModel, formControl или formControlName, как и для любого другого элемента управления формы.
<input
  type="text"
  [(ngModel)]="value"
  [disabled]="disabled"
  (input)="onChange(value)"
  (blur)="onTouched()"
/>

6. Используйте настраиваемый элемент управления формы:

  • Создайте форму, в которой вы хотите использовать настраиваемый элемент управления формы.
@Component(...)
export class AppComponent {
  form = new FormGroup({
    name: new FormControl(''),
  });
}
  • Включите настраиваемый компонент управления в форму в шаблоне.
<form [formGroup]="form">
  <app-custom-input formControlName="name"></app-custom-input>
</form>

Пользовательские валидаторы

Вот пример того, как добавить валидаторы в компонент пользовательского элемента управления 👇

1. В файле TypeScript компонента реализуйте интерфейс Validator.

import { Component, forwardRef } from '@angular/core';
import { 
  ControlValueAccessor, 
  NG_VALUE_ACCESSOR, 
  Validator 
} from '@angular/forms';

@Component(...)
export class CustomInputComponent implements ControlValueAccessor, Validator {}

2. Укажите токен NG_VALIDATORS и настройте его на использование функции forwardRef для ссылки на ваш пользовательский элемент управления.

import { Component, forwardRef } from '@angular/core'
import {
  ControlValueAccessor,
  NG_VALUE_ACCESSOR,
  Validator,
  NG_VALIDATORS
} from '@angular/forms'

@Component({
  selector: 'app-custom-input',
  templateUrl: './custom-input.component.html',
  styleUrls: ['./custom-input.component.css'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CustomInputComponent),
      multi: true
    },
    {
      provide: NG_VALIDATORS,
      useExisting: forwardRef(() => CustomInputComponent),
      multi: true
    }
  ]
})
export class CustomInputComponent implements ControlValueAccessor, Validator {}

3. Реализуйте метод validate в пользовательском компоненте управления.

Метод validate — это то место, где вы можете выполнить собственную логику проверки. Возвращая объект ValidationErrors с определенными ключами и значениями, вы можете предоставить настраиваемые сообщения об ошибках проверки для элемента управления формы. Если ошибок проверки нет, возврат null означает, что элемент управления считается действительным.

validate(control: AbstractControl): ValidationErrors | null {
    // Perform validation logic here
    if (!control.value || control.value === '') {
      return { required: true };
    }
    return null;
}

4. Обновите элемент управления формы в шаблоне родительского компонента, чтобы включить валидатор:

<form [formGroup]="form">
  <app-custom-input formControlName="name"></app-custom-input>
  <div *ngIf="form.controls.name.invalid && form.controls.name.touched">
    <span *ngIf="form.controls.name.errors?.required"
      >This field is required</span
    >
  </div>
</form>

Заключение

В заключение, создание настраиваемых элементов управления формами в Angular позволяет разработчикам создавать формы, персонализированные в соответствии с их конкретными потребностями и вариантами дизайна. Поняв, как работает модуль Angular Reactive Forms, и используя его компонентный подход, вы теперь можете создавать собственные элементы управления, которые будут одновременно функциональными и визуально привлекательными для ваших приложений.

Подведение итогов

Я надеюсь, что благодаря этой статье вы теперь знаете, как создавать собственные элементы управления формой в Angular. Если вы хотите увидеть весь пример, вы можете сделать это здесь, на StackBlitz ⚡️.

Если вам понравилось это читать, пожалуйста, хлопните в ладоши 👏 . Не стесняйтесь подписываться на меня и оставлять комментарии с вашими отзывами 👇.