Проверка угловой формы

Введение Одной из наиболее распространенных функций любого веб-приложения является предоставление пользователям формы для ввода некоторых данных. Вы используете формы ежедневно для входа в систему, регистрации, размещения заказов и т. Д. Обработка вводимых пользователем данных перед проверкой может иметь серьезные последствия. Вы можете в конечном итоге сохранить недопустимые данные, такие как неправильная дата, адрес электронной почты, возраст и т. Д. Это также может быть проблемой безопасности из-за атак, таких как межсайтовый скриптинг [https://en.wikipedia.org/wiki/Cross-site_scripting] (XSS). Традиционный способ проверки HTML

Вступление

Одна из наиболее распространенных функций любого веб-приложения - это предоставление пользователям формы для ввода некоторых данных. Вы используете формы ежедневно для входа в систему, регистрации, размещения заказов и т. Д.

Обработка вводимых пользователем данных перед проверкой может иметь серьезные последствия. Вы можете в конечном итоге сохранить неверные данные, такие как неправильная дата, адрес электронной почты, возраст и т. Д. Это также может быть проблемой безопасности из-за таких атак, как межсайтовый скриптинг (XSS).

Традиционный способ проверки HTML-форм - использование JavaScript или JQuery. К сожалению, этот подход требует большого количества кода.

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

Формы в Angular

Форма Angular - это обычная HTML-форма с несколькими дополнительными функциями. Для каждого поля (input, radio, select и т. Д.) В форме нам понадобится объект класса FormControl Объект FormControl предоставляет информацию об этом поле. Его value , если значение valid , а если оно недействительно, каковы errors проверки и т. Д.

Он также показывает состояние поля, такое как touched , untouched , dirty , pristine и т. Д.

Точно так же FormGroup - это коллекция объектов FormControl Каждая форма Angular имеет как минимум одну FormGroup . Вы можете решить использовать несколько FormGroup в таких случаях использования, как разделение разделов обработки личных и профессиональных данных в форме регистрации пользователя.

Все свойства FormGroup ( valid , error и т. Д.) Также доступны для FormControl . Например, valid свойство FormControl вернет true если все FormControl действительны.

Итак, чтобы добавить валидацию в форму Angular, нам нужны две вещи:

  • По крайней мере, один FormGroup для формы
  • Объект FormControl для каждого поля в форме

Есть два разных способа создания этих управляющих объектов. Мы можем предоставить некоторые директивы в шаблоне формы, и Angular может создать такие элементы управления для нас. Формы, созданные таким образом, называются формами на основе шаблонов .

Если у нас есть какие-то особые варианты использования и нам нужен больший контроль над формой, мы можем явно создавать такие объекты управления . Формы, созданные таким образом, называются реактивными формами .

Формы на основе шаблонов

В формах на основе шаблонов мы применяем ngModel для каждого поля в шаблоне. Angular создает FormControl под капотом для каждого такого поля и связывает его с соответствующим полем:

 <div class="form-group"> 
 <label for="name">Name</label> 
 <input type="text" class="form-control" id="name" 
 ngModel name="name"> 
 </div> 
 
 <div class="form-group"> 
 <label for="username">Username</label> 
 <input type="text" class="form-control" id="username" 
 ngModel name="username"> 
 </div> 

Примечание . Для ngModel требуется либо FormControl name либо определить FormControl как «автономный» в ngModelOptions , иначе Angular выдаст ошибку.

Кроме того, в app.module.ts вам нужно будет добавить FormsModule в массив импорта:

 import { FormsModule } from '@angular/forms'; 
 // ...some other imports 
 
 imports: [ 
 //...some other imports 
 FormsModule 
 ] 

Проверка в формах на основе шаблонов

Angular предоставил несколько встроенных валидаторов для проверки распространенных вариантов использования. Чтобы использовать встроенные валидаторы, вам нужно будет применить атрибуты валидации к каждому полю формы, где вы хотите валидацию. Эти атрибуты проверки такие же, как обычные атрибуты проверки HTML5, такие как required , minlength , maxlength и т. Д. В рамках hod Angular предоставил директивы для сопоставления этих атрибутов с функциями проверки, определенными в структуре Angular.

Каждый раз, когда значение FormControl изменяется, Angular генерирует список ошибок проверки, выполняя проверку. Если список пуст, это означает, что это действительный статус, в противном случае это недопустимый статус.

Допустим, мы хотим ввести в него следующие проверки:

  • Поскольку поля Name и Username имеют required атрибут, мы хотим отобразить сообщение проверки, если это поле оставлено пустым.
  • Поле имени должно иметь значение, minlegth и maxlength должны составлять 2 и 30 символов соответственно.
  • Если в имени пользователя есть пробелы, отобразить сообщение о недопустимом имени пользователя.

ngModel управления формой, в который мы хотим добавить проверку, нам нужно добавить соответствующие атрибуты проверки и экспортировать ngModel в локальную переменную шаблона :

 <input type="text" class="form-control" id="name" 
 required maxlength="30" minlength="2" 
 ngModel name="name" #name="ngModel"> 

В приведенном выше примере мы использовали следующие встроенные валидаторы - required , minlength и maxlength .

Мы можем использовать name переменной шаблона в шаблоне для проверки состояний валидации используемых валидаторов:

 <div *ngIf="name.invalid && (name.dirty || name.touched)" 
 class="alert alert-danger"> 
 <div *ngIf="name.errors.required"> 
 Name is required. 
 </div> 
 <div *ngIf="name.errors.minlength"> 
 Name cannot be more than 30 characters long. 
 </div> 
 <div *ngIf="name.errors.minlength"> 
 Name must be at least 2 characters long. 
 </div> 
 </div> 

Поскольку мы использовали условный оператор для рендеринга первого div , он будет отображаться только в том случае, если статус встроенного валидатора invalid . В начале раздела мы объяснили, как статус определяется как valid или invalid .

Точно так же внутренний div's будет отображаться только в том случае, если name переменной шаблона имеет свойство errors а errors имеет одно из следующих свойств - required , minlength и maxlength и значение свойства id true . Мы уже обсуждали, как переменная шаблона привязывается к ngModel и она получает эти свойства каждый раз, когда происходит какое-либо изменение в элементе управления формы и после того, как Angular запускает проверку для этого поля.

Примечание . Важно проверять состояние « dirty и « touched , в противном случае сообщение об ошибке будет отображаться при первой загрузке страницы, что плохо для пользователя. Нам нужно, чтобы сообщение проверки отображалось в одном из следующих условий:

  • Пользователь меняет какое-то значение, т.е. поле грязное ( formControlObject.dirty )
  • Пользователь использует табуляцию или щелчки для переключения фокуса на какой-либо другой элемент, т.е. к полю было прикосновение ( formControlObject.touched )

Если вы хотите сослаться на полный список встроенных валидаторов Angular, вы можете воспользоваться API валидаторов .

Написание собственного валидатора

Иногда встроенные валидаторы могут не соответствовать вашему конкретному варианту использования. В этом случае вам может потребоваться создать собственную функцию валидатора.

Функция валидатора реализует ValidatorFn , что означает, что у него должна быть подпись:

 interface ValidatorFn { 
 (control: AbstractControl): ValidationErrors | null 
 } 

ValidationErrors должен быть объектом, имеющим одну или несколько пар ключ-значение:

 type ValidationErrors = { 
 [key: string]: any; 
 }; 

Ключ должен быть строкой и используется для обозначения типа ошибки проверки, например, invalidEmail , required и т. Д. Значение может быть любым и используется для предоставления дополнительной информации об ошибке проверки.

В приведенном выше примере мы хотим написать настраиваемую функцию проверки, которая проверяет, нет ли пробелов в имени пользователя .

Хотя технически мы можем написать эту функцию в любом месте приложения, всегда рекомендуется помещать все связанные функции валидатора в отдельный класс:

 import { ValidationErrors, AbstractControl } from '@angular/forms'; 
 
 export class UserRegistrationFormValidators { 
 static usernameShouldBeValid(control: AbstractControl): ValidationErrors | null { 
 if ((control.value as string).indexOf(' ') >= 0) { 
 return { shouldNotHaveSpaces: true } 
 } 
 
 // If there is no validation failure, return null 
 return null; 
 } 
 } 

Примечание . В этом примере мы вернули true в качестве значения ключа shouldNotHaveSpaces потому что нам не нужно предоставлять какие-либо подробности. В некоторых случаях вам может потребоваться предоставить подробную информацию, например:

 return { maxlengthExceeded: { 
 maxLength: 20, 
 actual: control.value.length 
 } 
 } 

Затем мы можем использовать эту функцию валидатора UserRegistrationFormValidators.usernameShouldBeValid для username в нашей форме, управляемой шаблоном:

 <div class="form-group"> 
 <label for="username">Username</label> 
 <input type="text" class="form-control" id="username" 
 required 
 UserRegistrationFormValidators.usernameShouldBeValid 
 [(ngModel)]="person.username" name="username"> 
 </div> 

Реактивные формы

В реактивных формах мы создаем FormControl явно в компоненте этого шаблона. Вот обычная HTML-форма без каких-либо директив или ngModel

 <div class="form-group"> 
 <label for="name">Name</label> 
 <input type="text" class="form-control" id="name"> 
 </div> 
 
 <div class="form-group"> 
 <label for="username">Username</label> 
 <input type="text" class="form-control" id="username"> 
 </div> 

Предположим, мы хотим преобразовать нашу управляемую шаблоном форму из предыдущего примера в реактивную форму.

Для этого, во-первых, нам нужно явно создать FormGroup и FormControls для каждого поля в компоненте шаблона:

 form = new FormGroup({ 
 'name': new FormControl(), 
 'username': new FormControl(), 
 }) 

Примечание : Как обсуждалось ранее, форма может иметь более одной FormGroup . В этом случае у нас может быть вложенная структура:

 registrationForm = new FormGroup({ 
 'personalDetailsForm': new FormGroup({ 
 'name': new FormControl() 
 }) 
 }) 

Вы можете узнать больше о FormGroup в документации Angular .

Позвольте мне снова обратить ваше внимание на наш вариант использования.

Затем нам нужно связать эти FormControl с полями в форме HTML.

 <form [formGroup]="registrationForm"> 
 <div class="form-group"> 
 <label for="name">Name</label> 
 <input type="text" class="form-control" id="name" 
 [formControlName]="name"> 
 </div> 
 
 <div class="form-group"> 
 <label for="username">Username</label> 
 <input type="text" class="form-control" id="username" 
 [formControlName]="username"> 
 </div> 
 <form> 

Здесь мы применили formGroup и связали ее с объектом FormGroup registrationForm который мы создали в компоненте . Мы также связывали formControlName директиву с соответствующим FormControl объектами name и username .

Примечание . Директивы для создания реактивных форм определены в ReactiveFormsModule . Итак, если вы получите такую ошибку, как:

 Can't bind to formGroup 

... тогда вы должны проверить, импортировали ли вы этот ReactiveFormsModule в свой основной модуль app.module.ts .

Валидации в реактивных формах

В реактивных формах мы не ngModel а также не используем атрибуты проверки HTML5. Мы указываем валидаторы при создании объектов FormControl в самом компоненте.

Вот подпись класса FormControl

 class FormControl extends AbstractControl { 
 constructor(formState: any = null, validatorOrOpts?: ValidatorFn | AbstractControlOptions | ValidatorFn[], asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[]) 
 
 // ... 
 } 

Как мы видим, первый параметр - это начальное состояние элемента управления, которое можно оставить пустым, т.е. '' . Второй параметр - ValidatorFn .

Чтобы добавить встроенные функции валидатора для FormControl мы можем передать ему соответствующий ValidatorFn . В следующем примере мы использовали следующие встроенные валидаторы required , minLength и maxLength -:

 registrationForm = new FormGroup({ 
 'name': new FormControl('Enter your name', [ 
 Validators.required, 
 Validators.minLength(2), 
 Validators.maxLength(30) 
 ]), 
 'username': new FormControl('', Validators.required), 
 }) 

Примечание . Вам потребуется импортировать Validators в компонент.

Также обратите внимание, что в отличие от форм на основе шаблонов, мы не используем атрибуты проверки . Мы используем соответствующие ValidatorFn такие как Validators.required , Validators.minLength (2) и т. Д. Ваш редактор кода может обеспечивать автозаполнение для всех ValidatorFn тот момент, когда вы вводите Validators с точкой . .

Мы можем вернуться к шаблону и написать сообщения проверки:

 <form [formGroup]="registrationForm"> 
 <div class="form-group"> 
 <label for="name">Name</label> 
 <input type="text" class="form-control" id="name" 
 [formControlName]="name"> 
 <div *ngIf="registrationForm.get('name').invalid && (registrationForm.get('name').dirty || registrationForm.get('name').touched)" 
 class="alert alert-danger"> 
 <div *ngIf="registrationForm.get('name').errors.required"> 
 Name is required. 
 </div> 
 <div *ngIf="registrationForm.get('name').errors.minlength"> 
 Name cannot be more than 30 characters long. 
 </div> 
 <div *ngIf="registrationForm.get('name').errors.minlength"> 
 Name must be at least 2 characters long. 
 </div> 
 </div> 
 </div> 
 
 <div class="form-group"> 
 <label for="username">Username</label> 
 <input type="text" class="form-control" id="username" 
 [formControlName]="username"> 
 </div> 
 <form> 

Пользовательские валидаторы для реактивных форм

Нам нужно написать настраиваемую функцию валидатора так же, как мы это сделали для раздела формы, управляемой шаблоном. Мы можем использовать ту же настраиваемую функцию валидатора UserRegistrationFormValidators.usernameShouldBeValid в компоненте для реактивной формы :

 registrationForm = new FormGroup({ 
 'name': new FormControl('Enter your name', [ 
 Validators.required, 
 Validators.minLength(2), 
 Validators.maxLength(30) 
 ]), 
 'username': new FormControl('', [ 
 Validators.required, 
 UserRegistrationFormValidators.usernameShouldBeValid 
 ]), 
 }) 

Заключение

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

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

comments powered by Disqus