【问题标题】:Angular2: Form Build + asynchronous data loadingAngular2:表单构建+异步数据加载
【发布时间】:2016-05-12 21:50:33
【问题描述】:

我有一个使用表单生成器(Angular2 Beta 1,TypoScript)创建的表单,即:constructor 中有这样的内容:

this.form = this._formBuilder.group({
    'username': ['', Validators.required],
    'email': ['', Validators.required]
});

表格出现了,到目前为止一切都很好。我没有真正了解的是当我从远程服务(或其他一些异步加载机制)加载数据(在本例中为 User 对象)时如何处理绑定。

我尝试过的是:

  • constructorngOnInit 中异步加载数据。问题:甚至在加载开始之前引发异常(“无法读取未定义的属性 'validator' ...”)
  • constructorngOnInit 中异步加载数据,但在此之前创建一个空表单。问题:验证不起作用。
  • 我期望的工作:将表单数据绑定到User 对象的属性,并设置该对象的属性。问题:也不例外,但表格中没有显示数据。

我想一定有一些更聪明/更好的方法来让它工作?我对 Angular2 比较陌生,所以我希望这个问题不会太愚蠢……

---- 更新----

首先,我忘了提到我在表单中使用了ngFormModel——以防它很重要。

和@Thierry:我认为“与表单绑定的临时空对象”是我尝试做的(上面提到的第三种方法)但没有奏效。准确地说,我试过这个:

constructor(private _formBuilder:FormBuilder) {
    this.user = new User;
    this.user.username = 'abc';
    this.form = this._formBuilder.group({
        'username': [this.user.username, Validators.required],
    });
}

这会显示用户名,但是当我将设置 this.user.username 的行移到构造函数的末尾时它甚至都不起作用——我觉得这很令人惊讶,因为我希望数据绑定来处理这个问题.

【问题讨论】:

  • 您确定临时空对象吗? ;-) 见我的 plunkr:plnkr.co/edit/metUkOB7Sqfyr9DtCLR0?p=preview。即使在数据加载后验证仍然有效...
  • 有趣。也许这是“模板驱动”与“模型驱动”Ang2 形式的问题。我使用后一种方法,并且在控件中没有 [(ngModel)] - 这可能是它在这里不起作用的原因吗?
  • 是的,我也使用模型驱动的方法。如果没有ngModel,您需要手动设置每个控件的值...ngModel 不是这种情况:更新全局对象,每个绑定的属性都会自动更新;-)

标签: angular angular2-forms


【解决方案1】:

我看到了几个解决方案:

  • 利用*ngIf 仅在数据存在时显示表单
  • 利用 @CanActivate 装饰器(如果您使用路由)来显示表单所在的组件,仅当数据存在时
  • 使用临时空对象与表单绑定。当数据存在时,您可以使用接收到的数据填充(或覆盖)此对象。

这里有一个 plunkr:https://plnkr.co/edit/metUkOB7Sqfyr9DtCLR0?p=preview

希望对你有帮助 蒂埃里

【讨论】:

    【解决方案2】:

    您可以在 Control 对象中分隔您的用户名和电子邮件,而不是将其附加到表单中。您将拥有更多控制权(您可以稍后更新)。

    form: ControlGroup;
    email: Control = new Control("");
    name: Control = new Control("");
    constructor(public fb: FormBuilder) {
     this.form = fb.group({
            email: this.email,
            name: this.name
        });
    
        setTimeout(() => {
            this.email.updateValue("invalid email");
            this.name.updateValue("Name");
        }, 3000);
    }
    

    Plunker example

    【讨论】:

    • 分离是关键。谢谢。
    【解决方案3】:

    您还可以在加载数据后更新 FormGroup 中的各个控件。例如:

    this._http.get('/user/123')
        .map(response => response.json())
        .subscribe(user => {
            this.form.find('username').updateValue(user.username);
            this.form.find('email').updateValue(user.email);
        })
    

    重要的是,您可以在 formGroup 1 中找到控件实例并更新其值。或者简单

    this.form.controls.username.updateValue(user.username)
    

    也可以。

    UPD。请注意,在最近的版本中,API 已更改,因此您需要使用 getter 访问 username

    this.form.get('username').setValue(user.username)
    

    【讨论】:

    • 我是否可以正确假设这也会更新视图中的值?
    • 小更新,发现已被删除...现在是this.form.get('username').setValue(user.username);
    • 答案应该更新,form.find 被移除
    【解决方案4】:

    使用this.form.setValues({username: this.user.username, mail: this.user.mail})

    【讨论】:

    • 您好 jfreire,感谢您的回答!您的代码可能是正确的,但在某些上下文中它会给出更好的答案;例如,您可以解释这个提议的更改如何以及为什么会解决提问者的问题,可能包括指向相关文档的链接。这将使它对他们更有用,对正在寻找类似问题的解决方案的其他网站读者也更有用。
    猜你喜欢
    • 1970-01-01
    • 2020-06-05
    • 2016-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-06
    • 1970-01-01
    • 2017-05-23
    相关资源
    最近更新 更多