アプリケーションでフォームコントロールを有効または無効にできません。これはおそらく、フォームが非同期コンテキストで有効/無効にされているためです。
コードは次のとおりです。
user.component.html
_<form [formGroup]="form">
<input type="text" id="name" formControlName="name" />
<input type="text" id="age" formControlName="age" />
</form>
_
user.component.ts
_ngOnInit() {
this._route.queryParams.subscribe(params => {
getUser(params.userId).subscribe(user => {
this._buildForm(user);
})
});
}
private _buildForm(user){
this.form = _fb.group({
name: [{value: user.name, disabled: user.someCondition}, Validators.required],
age: [{value: user.age, disabled: user.anotherCondition}, Validators.required]
})
}
_
ユーザーがパラメーターの変更時に初めて読み込まれるとき、コントロールは関連する条件に基づいて有効/無効になります。その後パラメータが変更されても、値は適切に設定されていますが、コントロールの状態は同じです。
私はこれを修正するためにさまざまな方法を試しましたが、助けにはなりません。たとえば、__buildForm
_メソッドの最後で次のことを試しました。
_this.form.disable() //Doesn't do anything
this.form.controls.name.disable(); //Doesn't help
_
期待どおりに機能する1つのことは次のとおりです(ただし、これは必須ではありません)。
_<button (click)="form.disable()" value="Disable Form" />
<button (click)="form.enable()" value="Enable Form" />
_
私が感じるのは、問題は_buildForm()
が非同期コンテキスト(subscribeメソッド)から呼び出されているという事実によるものだと思います。
この問題を解決するにはどうすればよいですか?
[〜#〜]更新[〜#〜]
Observableサブスクリプションは、以下のナビゲーションに基づいてトリガーされることに注意してください。
_this._router.navigate([], {
relativeTo: this._route,
queryParams: {userId: 10}
})
_
UPDATE 2https://angular-cvf1fp.stackblitz.io
これは私の問題を理解する簡単な方法です
あなただけのフォームコントロールの有効化/無効化メソッドが必要です。
これがstackblitz example です。それは完全に動作します。
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
group;
isDisabled = true;
constructor(fb: FormBuilder) {
this.group = fb.group({
stuff: fb.control({value: 'stuff', disabled: this.isDisabled})
});
}
toggle() {
this.isDisabled = !this.isDisabled;
this.group.controls.stuff[this.isDisabled ? 'enable' : 'disable']();
}
}
あなたが正しい。サブスクリプションは一度だけ発生するため、フォームを送信した後、ユーザーエンティティは変更されません。これを行うには、たとえば、フォーム送信にイベントハンドラを追加します。
ser.component.html
<form [formGroup]="form" (submit)="_updateForm()">
<input type="text" id="name" fromControlName="name" />
<input type="text" id="age" fromControlName="age" />
</form>
ser.component.ts
private userId: any;
ngOnInit() {
this._route.queryParams.subscribe(params => {
this.userId = params.userId;
this._updateForm();
});
}
private _buildForm(user){
this.form = _fb.group({
name: [{value: user.name, disabled: user.someCondition}, Validators.required],
age: [{value: user.age, disabled: user.anotherCondition}, Validators.required]
});
}
// The update function has to be public to be called inside your template
public _updateForm(){
getUser(this.userId).subscribe(user => {
this._buildForm(user);
});
}
<form [formGroup]="form">
<input type="text" id="name" fromControlName="name" />
<input type="text" id="age" fromControlName="age" />
</form>
ここにタイプミスがありますか?fromControlName
はformControlName
になるはずです変更後、切り替えが機能します;)
formGroup
にngOnit
を直接作成します。デフォルトでは無効になっているため、非同期の問題を心配せずに存在することが確認できます。this._route.queryParams.subscribe(...)
では、this.form.setValue({//set all control values})
またはthis.form.patchValue({//set individual controls})
を使用して、必要に応じて、または利用可能になったら、個々のコントロールを更新できます。condition
およびsomeOtherCondition
のコンポーネントインスタンス変数を使用します(または、データモデルをフォームのモデルから分離したい場合は、全体としてuser
オブジェクトを使用します。同じである)。これらを「false」に初期化し、代わりにformGroup作成でコントロールを有効/無効にするために参照してください。 user
データモデルへの直接のアクセスを待つのではなく、ユーザーデータが配置されたら、同じ.subscribe()
ブロック内のこれらの変数を更新することもできます。このようにして、非同期データが利用可能になるまで、コントロールとformGroupが存在し、無効になります。