In my Angular application, I have a lot of reactive forms with text inputs that all need Error messages, which is a lot of duplicated code. I wanted to create a custom component for the mat form field, but I am struggling to make it work. This is my template:
<mat-form-field fxLayout="column" fxLayoutAlign="start stretch">
<mat-label>{{label}}</mat-label>
<input matInput type="{{inputType}}" autocomplete="username" [formControl]="formControl">
<mat-error *ngIf="formControl.touched && formControl.errors?.required">
Bitte geben Sie den {{label}} an!
</mat-error>
<mat-error *ngIf="formControl.touched && formControl.errors?.maxlength">
Der {{label}} darf nicht mehr als {{maxLength}} Zeichen haben!
</mat-error>
<mat-error *ngIf="formControl.touched && formControl.errors?.minlength">
Der {{label}} darf nicht weniger als {{minLength}} Zeichen haben!
</mat-error>
</mat-form-field>
<ng-container *ngIf="formControl.touched && formControl.invalid">
<br/>
</ng-container>
The component:
export class FormFieldComponent {
@Input() formControl: FormControl;
@Input() inputType: "color" | "date" | "datetime-local" |
"email" | "month" | "number" | "password" | "search" |
"tel" | "text" | "time" | "url" | "week" = "text"
@Input() appearance: 'legacy' | 'fill' | 'standard' | 'outline' = 'standard';
@Input() label: string;
@Input() minLength: number;
@Input() maxLength: number;
}
In my Form I want to call the component like this:
<mat-card >
<form [formGroup]="form" (ngSubmit)="login()">
<mat-card-title style="text-align: center">Login</mat-card-title>
<mat-card-content fxLayout="column" fxLayoutAlign="start stretch">
<app-form-field [formControl]="form.controls.userName" [maxLength]="userNameMaxLength" [minLength]="userNameMinLength" [label]="'Benutzername'"></app-form-field>
<app-form-field [formControl]="form.controls.password" [maxLength]="passwordMaxLength" [minLength]="passwordMinLength" [label]="'Passwort'" [inputType]="'password'"></app-form-field>
<ng-container *ngIf="loginFailed && formWasSubmitted">
<br>
<mat-error>
Authentifizierung fehlgeschlagen.
Bitte überprüfen Sie ihren
Benutzernamen und ihr Password.
</mat-error>
<br>
</ng-container>
<div fxLayout="column" fxLayoutAlign="start center">
<button type="submit" mat-raised-button color="primary">Login</button>
</div>
</mat-card-content>
</form>
</mat-card>
The problem is that in the console I get the following error:
core.mjs:6485 ERROR Error: No value accessor for form control with unspecified name attribute
at _throwError (forms.mjs:1785:11)
at setUpControl (forms.mjs:1576:13)
at FormControlDirective.ngOnChanges (forms.mjs:5126:13)
at FormControlDirective.rememberChangeHistoryAndInvokeOnChangesHook
CodePudding user response:
It's a problem with the "name" of the input formControl
, you can use some like
@Input('control') formControl: FormControl;
and use
<app-form-field [control]="control"..>
BTW: it's unnecesary check if touched in a mat-error (by defect a mat-error only show if the formControl is touched) so, e.g. is enought
<mat-error formControl.errors?.minlength">
Der {{label}} darf nicht weniger als {{minLength}} Zeichen haben!
</mat-error>