【问题标题】:Angular 4 - Reactive Forms enable/disable not workingAngular 4 - 反应式表单启用/禁用不起作用
【发布时间】:2018-10-07 13:12:34
【问题描述】:

我在我的应用程序中启用和禁用表单控件时遇到问题。这可能是因为表单在异步上下文中被启用/禁用。

代码如下。

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

按预期工作的一件事如下(但这不是必需的)。

<button (click)="form.disable()" value="Disable Form" />
<button (click)="form.enable()" value="Enable Form" />

我的感觉是,问题在于 _buildForm() 是从异步上下文(订阅方法)中调用的。

我该如何解决这个问题?

更新

请注意,Observable 订阅是基于如下导航触发的。

this._router.navigate([], {
   relativeTo: this._route,
   queryParams: {userId: 10}
})

更新 2 https://angular-cvf1fp.stackblitz.io

这是理解我的问题的一种更简单的方法

【问题讨论】:

  • 我不清楚。您要在所有输入完成之前禁用提交?
  • 你的角度版本是多少?
  • 你可以为它做一个 plunker 或 ...
  • 这是 Angular 4。我可以尝试为它制作一个 plunker。
  • 在你的标题中你写了Angular 2,你不是@KashifNazar吗?

标签: javascript angular angular-reactive-forms disabled-input


【解决方案1】:
  • 直接在ngOnit 中创建formGroup,默认情况下禁用控件,这样您就可以确定它存在而无需担心异步问题。
  • this._route.queryParams.subscribe(...) 中,您可以使用this.form.setValue({//set all control values})this.form.patchValue({//set individual controls}) 根据需要/一旦可用来更新各个控件。
  • conditionsomeOtherCondition 使用组件实例变量(如果要将数据模型与表单模型分开,则将user 对象作为一个整体使用——它们不必相同)。将这些初始化为“false”,并引用它们来启用/禁用 formGroup 创建中的控件。用户数据到位后,您还可以在同一 .subscribe() 块中更新这些变量,而无需等待直接访问 user 数据模型。

这样,您的控件和 formGroup 就会存在并被禁用,直到异步数据可用为止。

【讨论】:

    【解决方案2】:
    <form [formGroup]="form">
        <input type="text" id="name" fromControlName="name" />
        <input type="text" id="age" fromControlName="age" />
    </form>
    

    你在这里看到错字了吗?fromControlName 应该是formControlName 之后,切换将起作用;)

    https://angular-rivxs5.stackblitz.io

    【讨论】:

    • 不错的收获。代码中没有这个错字。它就在这里。让我纠正一下。
    【解决方案3】:

    你是对的。订阅只触发一次,因此在提交表单后,用户实体不再更改。为此,请在表单提交中添加一个事件处理程序。

    user.component.html

    <form [formGroup]="form" (submit)="_updateForm()">
        <input type="text" id="name" fromControlName="name" />
        <input type="text" id="age" fromControlName="age" />
    </form>
    

    user.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);
        });
    }    
    

    【讨论】:

    • 感谢您的回答。只要参数发生变化,订阅方法就会触发多次。 (userId)
    【解决方案4】:

    您只需要启用/禁用表单控件的方法。

    这里是 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']();
      }
    }
    

    【讨论】:

    • 感谢您的回答,但问题是我试图从订阅方法切换。如果我在 UI 中有一个按钮,则可以轻松启用/禁用该组件。让我尝试修改示例。
    • 你设置了 ChangeDetectionStrategy 吗?
    • 没有。我没有
    • 我更新到订阅。有用。即使使用 ChangeDetectionStrategy.OnPush。
    • 好的,然后在 stackblitz 上提供复制。到时候我们会很容易解决的。
    猜你喜欢
    • 2018-11-13
    • 2019-11-15
    • 1970-01-01
    • 2019-01-26
    • 1970-01-01
    • 1970-01-01
    • 2019-05-31
    • 1970-01-01
    • 2018-02-01
    相关资源
    最近更新 更多