カスタムフォームコントロールコンポーネントがあります(これは栄光の入力です)。カスタムコンポーネントである理由は、UIの変更を容易にするためです。つまり、基本的に入力コントロールのスタイルを変更すると、アプリケーション全体に変更を簡単に反映させることができます。
現在、Angular https://material.angular.io でマテリアルデザインを使用しています
どのスタイルが無効な場合に非常にうまく制御します。
完全に機能するカスタムコンポーネントにformControlNameを渡すことができるように、ControlValueAccessorを実装しました。カスタムコントロールが有効/無効であり、アプリケーションが期待どおりに機能する場合、フォームは有効/無効です。
ただし、問題は、カスタムコンポーネント内の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]
});
答えはここにあります:
AngularのカスタムフォームコンポーネントからFormControlへのアクセスを取得
これが最善の方法であるかどうかはわかりませんが、誰かがよりきれいな方法を見つけるのが大好きですが、この方法で取得したフォームコントロールに子入力をバインドすると、問題が解決しました
DIを通じてNgControl
にアクセスできます。 NgControl
には、検証ステータスに関するすべての情報があります。 NgControl
を取得するには、NG_VALUE_ACCESSOR
を介してコンポーネントを提供するのではなく、コンストラクタでアクセサを設定する必要があります。
@Component({
selector: 'custom-form-comp',
templateUrl: '..',
styleUrls: ...
})
export class CustomComponent implements ControlValueAccessor {
constructor(@Self() @Optional() private control: NgControl) {
this.control.valueAccessor = this;
}
// ControlValueAccessor methods and others
public get invalid(): boolean {
return this.control ? this.control.invalid : false;
}
public get showError(): boolean {
if (!this.control) {
return false;
}
const { dirty, touched } = this.control;
return this.invalid ? (dirty || touched) : false;
}
}
完全な情報を知るには、この 記事 を参照してください。
加えて:汚いと考えられるかもしれませんが、それは私にとってはトリックです: