Angular 4 - Reactive Forms enable/disable not working
我在我的应用程序中启用和禁用表单控件时遇到问题。这可能是因为表单在异步上下文中被启用/禁用。
代码如下。
user.component.html
1 2 3 4 | <form [formGroup]="form"> <input type="text" id="name" formControlName="name" /> <input type="text" id="age" formControlName="age" /> </form> |
user.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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] }) } |
当用户第一次在参数更改时加载时,控件会根据其相关条件启用/禁用。当参数随后发生变化时,控件的状态保持不变,尽管值设置得当。
我尝试了不同的方法来解决这个问题,但没有任何帮助。例如,我在
1 2 3 | this.form.disable() //Doesn't do anything this.form.controls.name.disable(); //Doesn't help |
按预期工作的一件事是以下(但这不是必需的)。
1 2 | <button (click)="form.disable()" value="Disable Form" /> <button (click)="form.enable()" value="Enable Form" /> |
我的感觉是问题在于
我该如何解决这个问题?
更新
请注意,Observable 订阅是基于如下导航触发的。
1 2 3 4 | this._router.navigate([], { relativeTo: this._route, queryParams: {userId: 10} }) |
更新 2
https://angular-cvf1fp.stackblitz.io
这是理解我的问题的一种更简单的方法
你只需要启用/禁用表单控制的方法。
这里是 stackblitz 的例子。效果很好。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | @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'](); } } |
-
formGroup 直接在ngOnit 中创建,默认情况下禁用控件,因此您确定它存在而无需担心异步问题。 -
在
this._route.queryParams.subscribe(...) 中,您可以使用this.form.setValue({//set all control values}) 或this.form.patchValue({//set individual controls}) 根据需要/一旦可用来更新各个控件。 -
为
condition 和someOtherCondition 使用组件实例变量(如果您想将数据模型与表单模型分开,则使用一个整体的user 对象 - 它们不必相同)。将这些初始化为"false",并引用它们来启用/禁用 formGroup 创建中的控件。一旦用户数据到位,您还可以在同一.subscribe() 块中更新这些变量,而不是等待直接访问user 数据模型。
这样,您的控件和 formGroup 就会存在并被禁用,直到异步数据可用。
你是对的。订阅只触发一次,因此在提交表单后,用户实体不再更改。为此,请在表单提交中添加一个事件处理程序。
user.component.html
1 2 3 4 | <form [formGroup]="form" (submit)="_updateForm()"> <input type="text" id="name" fromControlName="name" /> <input type="text" id="age" fromControlName="age" /> </form> |
user.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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); }); } |
1 2 3 4 | <form [formGroup]="form"> <input type="text" id="name" fromControlName="name" /> <input type="text" id="age" fromControlName="age" /> </form> |
你看到这里有错字吗?
之后,切换将起作用;)
https://angular-rivxs5.stackblitz.io