我有一个自定义表单控件组件(它是一个高级输入框)。之所以使用自定义组件,是为了方便UI更改 - 即如果我们从根本上更改样式输入控件的方式,很容易在整个应用程序中传播这种更改。
目前,我们在Angular中使用Material Design https://material.angular.io,当控件无效时,它会非常好地设置控件样式。
我们已经实现了ControlValueAccessor,以便允许我们将formControlName传递给我们的自定义组件,这个功能完美地工作;当自定义控件有效/无效时,表单也是有效/无效的,应用程序按预期运行。
然而,问题在于我们需要根据是否有效来设置自定义组件内部的UI样式,但我们似乎做不到 - 实际需要设置样式的输入框从未得到验证,它只是将数据传递给父组件。
COMPONENT.ts
目前,我们在Angular中使用Material Design https://material.angular.io,当控件无效时,它会非常好地设置控件样式。
我们已经实现了ControlValueAccessor,以便允许我们将formControlName传递给我们的自定义组件,这个功能完美地工作;当自定义控件有效/无效时,表单也是有效/无效的,应用程序按预期运行。
然而,问题在于我们需要根据是否有效来设置自定义组件内部的UI样式,但我们似乎做不到 - 实际需要设置样式的输入框从未得到验证,它只是将数据传递给父组件。
COMPONENT.ts
import { Component, forwardRef, Input, OnInit } from '@angular/core';
import {
AbstractControl,
ControlValueAccessor,
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
ValidationErrors,
Validator,
} from '@angular/forms';
@Component({
selector: 'app-input',
templateUrl: './input.component.html',
styleUrls: ['./input.component.css'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => InputComponent),
multi: true
}
]
})
export class InputComponent implements OnInit, ControlValueAccessor {
writeValue(obj: any): void {
this._value = obj;
}
registerOnChange(fn: any): void {
this.onChanged = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
setDisabledState?(isDisabled: boolean): void {
this.disabled = isDisabled;
}
get value() {
return this._value;
}
set value(value: any) {
if (this._value !== value) {
this._value = value;
this.onChanged(value);
}
}
@Input() type: string;
onBlur() {
this.onTouched();
}
private onTouched = () => {};
private onChanged = (_: any) => {};
disabled: boolean;
private _value: any;
constructor() { }
ngOnInit() {
}
}
COMPONENT.html
<ng-container [ngSwitch]="type">
<md-input-container class="full-width" *ngSwitchCase="'text'">
<span mdPrefix><md-icon>lock_outline</md-icon> </span>
<input mdInput placeholder="Password" type="text" [(ngModel)]="value" (blur)="onBlur()" />
</md-input-container>
</ng-container>
在页面上的使用示例:
HTML:
<app-input type="text" formControlName="foo"></app-input>
TS:
this.form = this.fb.group({
foo: [null, Validators.required]
});