我以為我有幾乎相同的例子,但不知何故控制元件欺騙了我:-/
<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>?它甚至沒有出現。
uj5u.com熱心網友回復:
重用了附加的代碼,懷疑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 上的示例演示
uj5u.com熱心網友回復:
感謝@Yong Shun我想出了如何正確進行管理。似乎需要input使用常規模板驅動方法(用于input欄位更新)包裝一個欄位,并將此組件用作回應式組件。所以我的自定義控制元件內部有一個處理狀態的控制元件。
我從原始代碼中洗掉了所有不必要的內容,并從指南中包含了一些小提示。
所以這是我的(簡化的)作業示例- 為了當有人再次需要它時。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/349614.html
下一篇:在管道中使用擴展替換值
