角度材料自定义表单域不显示垫子错误



我以为我有几乎相同的例子,但不知怎么的,控制欺骗了我:-/

<form [formGroup]="form">
<app-ref-urlcheck [maxLen]="20" formControlName="url"></app-ref-urlcheck>
</form>

模板看起来像

<mat-form-field>
<input matInput #inUrl="ngModel" [(ngModel)]="value" type="url" [attr.maxlength]="maxLen" [errorStateMatcher]="errorStateMatcher"
(input)="changeInput(inUrl.value)" [disabled]="isDisabled" [value]="strUrl" 
placeholder="Homepage" />
<mat-error>test error</mat-error> <!-- doesn't show up - neither the next -->
<mat-error *ngIf="(inUrl.touched && inUrl.invalid)">This field is required</mat-error>
</mat-form-field>

和主要内容

import { Component, HostListener, Input, OnInit } from '@angular/core';
import { AbstractControl, ControlValueAccessor, FormControl, NgControl, NG_VALIDATORS, NG_VALUE_ACCESSOR, ValidationErrors, Validator } from '@angular/forms';
import { ErrorStateMatcher } from '@angular/material/core';
import { MatFormFieldControl } from '@angular/material/form-field';
import { Observable } from 'rxjs';
@Component({
selector: 'app-ref-urlcheck',
templateUrl: './ref-urlcheck.component.html',
styleUrls: ['./ref-urlcheck.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: RefURLcheckComponent
},
{
provide: NG_VALIDATORS,
multi: true,
useExisting: RefURLcheckComponent
}
]
})
export class RefURLcheckComponent implements OnInit, ControlValueAccessor, MatFormFieldControl<any>, Validator {
@Input() maxLen = 254;
strUrl: string;
onChange = (changedUrl) => { };
onTouched = () => { };
isDisabled = false;
touched = false;
@HostListener('focusin', ['$event.target.value']) onFocusIn;
constructor() { }
onContainerClick(event: MouseEvent): void {
throw new Error('Method not implemented.');
}
setDescribedByIds(ids: string[]): void {
throw new Error('Method not implemented.');
}
userAriaDescribedBy?: string;
autofilled?: boolean;
controlType?: string;
errorState: boolean;
disabled: boolean;
required: boolean;
shouldLabelFloat: boolean;
empty: boolean;
focused: boolean;
ngControl: NgControl;
placeholder: string;
id: string;
stateChanges: Observable<void>;
value: any;
ngOnInit(): void {
}
setDisabledState?(isDisabled: boolean): void {
this.isDisabled = isDisabled;
}
registerOnTouched(onTouched: () => {}): void {
this.onTouched = onTouched;
}
registerOnChange(onChange: (changedValue: string) => {}): void {
this.onChange = onChange;
this.onFocusIn = (inputVal) => {
console.log('focus in', inputVal);
this.markAsTouched();
};

}
writeValue(value: string): void {
this.strUrl = value;
}
markAsTouched() {
if (!this.touched) {
this.onTouched();
this.touched = true;
}
}
changeInput(inVal: string) {
this.onChange(inVal);
this.markAsTouched();
}

readonly errorStateMatcher: ErrorStateMatcher = {
isErrorState: (ctrl: FormControl) => {
console.log('errorStateMatch...')
this.errorState = true;
return (ctrl && ctrl.invalid);
}
};
validate(control: AbstractControl): ValidationErrors | null {
if (control?.value.length <= 5) {
this.errorState = true;
return {
tooShort: true
};
}
this.errorState = false;
return null;
}
}

与参考示例中的问题相同:如何显示<mat-error>?它根本就没有出现。

重用了附加的代码,并怀疑验证失败时FormControl没有更新并出现错误。

验证失败时,应将错误设置为FormControl,如下所示:

this.inUrl.control.setErrors({ tooShort: true });
import { ViewChild } from '@angular/core';
export class RefURLcheckComponent
implements OnInit, ControlValueAccessor, MatFormFieldControl<any>, Validator
{
@ViewChild('inUrl', { static: true }) inUrl: NgControl;
...
validate(control: AbstractControl): ValidationErrors | null {
if (control?.value?.length <= 5) {
this.errorState = true;
this.inUrl.control.setErrors({ tooShort: true });
return {
tooShort: true,
};
}
this.errorState = false;
this.inUrl.control.setErrors(null);
return null;
}
}

StackBlitz 上的示例演示

Thanx to@Yong Shun我想好了如何正确管理。似乎需要用常规模板驱动的方法包装input字段(用于input字段的更新(,并将该组件用作反应组件。所以我的自定义控件有一个处理状态的控件。

我从我的原始代码中删除了所有不必要的东西,并从指南中包含了一些小提示。

因此,这是我的(精简的(工作示例——为了有人再次需要它。

相关内容

最新更新