Шаблон реактивных форм углового материала - как создать компонент для этого шаблона с помощью ControlValueAccessor
Работа с угловыми материалами mat-form-field
и реактивные формы. В проекте у меня есть повторяющийся шаблон, который выглядит следующим образом
// ts
this.formGroup = this.formBuilder.group({
name: ['', ServerValidation]
})
<!-- html -->
<div [formGroup]="formGroup">
<mat-form-field>
<input
matInput
formControlName="name"
[placeholder]="'Name'"
name="name"
/>
<mat-error
*ngIf="
formGroup
.get('name')
.hasError('serverValidation')
"
>
{{
formGroup
.get("name")
.getError("serverValidation")
}}
</mat-error>
</mat-form-field>
</div>
Это высокий уровень - принимая, что я могу получать ошибки проверки с сервера - как я могу повторить этот шаблон http-шаблона в компоненте? У меня есть догадка, что я должен использовать ControlValueAccessor - но не знаю, как это сделать.
Реализация, которую я представляю, может выглядеть примерно так
<!-- html -->
<div [formGroup]="formGroup">
<serverValidatedInput formControlName="'name'">
<mat-error>error message for client side validation</mat-error>
</serverValidatedInput>
</div>
По сути, я хочу использовать этот пользовательский компонент как обычный материал ввода (более или менее), за исключением того, что он поставляется с ошибкой проверки сервера по умолчанию. Кто-нибудь может дать мне какое-то направление здесь - спасибо.:)
1 ответ
Есть два способа сделать это - простой и сложный. Сложный путь заключается в реализации ControlValueAccessor
и это дает вам больше гибкости в использовании компонента. Самый простой способ - просто передать вещи через ваш компонент фактическим элементам формы внутри. Если вам не нужна гибкость в использовании этого компонента, выберите легкий путь.
Во-первых, вам нужно избавиться от идеи использования mat-error
вне mat-form-control
, Это просто не сработает, и вам не нужно, чтобы это работало. Оставьте его внутри поля формы и предоставьте для него содержимое. Наряду с этим примените свою логику ошибок к содержанию mat-error
не к mat-error
сам. И помните, что вам не нужна логика для отображения mat-error
- поле формы автоматически позаботится об этом, когда элемент управления формы имеет ошибку. Вам нужна только логика, чтобы определить содержание ошибки.
Простая обертка для mat-form-field
будет выглядеть примерно так:
моя форма-field.html
<mat-form-field>
<input matInput type="text" [placeholder]="placeholder" [formControl]="myFormControl" required>
<mat-error>
<ng-content></ng-content>
</mat-error>
</mat-form-field>
мой форм-field.ts
import {Component, Input} from '@angular/core';
import {FormControl} from '@angular/forms';
@Component({
selector: 'my-form-field',
templateUrl: 'my-form-field.html'
})
export class MyFormField {
@Input() myFormControl: FormControl;
@Input() placeholder: string;
}
использование
пользовательских форм-поля example.html
<form [formGroup]="formGroup">
<my-form-field placeholder="Name" [myFormControl]="formGroup.get('name')">
<ng-container *ngIf="formGroup.get('name').hasError('required')">
This field is required
</ng-container>
<ng-container *ngIf="formGroup.get('name').hasError('serverValidation')">
Server validation failed
</ng-container>
</my-form-field>
</form>
пользовательских форм-поля-example.ts
import {Component} from '@angular/core';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {ServerValidation} from '...';
@Component({
selector: 'custom-form-field-example',
templateUrl: 'custom-form-field-example.html'
})
export class CustomFormFieldExample {
formGroup: FormGroup;
constructor(formBuilder: FormBuilder) {
this.formGroup = formBuilder.group({
name: ['', [Validators.required, ServerValidation]]
});
}
}