Angular2:表单构建+异步数据加载
Angular2: Form Build + asynchronous data loading
我有一个使用 Form Builder(Angular2 Beta 1,TypoScript)创建的表单,即:constructor
中有类似这样的内容:
this.form = this._formBuilder.group({
'username': ['', Validators.required],
'email': ['', Validators.required]
});
表格出现了,到目前为止一切都很好。我没有真正了解的是当我从远程服务(或其他一些异步加载机制)加载数据(在本例中为用户对象)时如何处理绑定。
我试过的是:
- 在
constructor
或ngOnInit
中异步加载数据。问题:抛出异常,甚至在加载开始之前(“无法读取 属性 'validator' of undefined …”)
- 在
constructor
或 ngOnInit
中异步加载数据,但在此之前创建一个空表单。问题:验证不起作用。
- 我期望的工作:将表单数据绑定到
User
对象的属性,并设置该对象的属性。问题:没有异常,但是数据没有显示在表格中。
我想一定有一些 smarter/better 方法可以让它工作?我是 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
的行移动到构造函数的末尾时,它甚至不起作用——这让我感到非常惊讶,因为我希望数据绑定到处理好这个。
我看到了几个解决方案:
- 利用
*ngIf
仅当数据存在时才显示表单
- 利用
@CanActivate
装饰器(如果您使用路由)显示表单所在的组件,仅当数据存在时
- 使用临时空对象与表单绑定。当数据存在时,您可以用收到的数据填充(或覆盖)该对象。
这是一个 plunkr:https://plnkr.co/edit/metUkOB7Sqfyr9DtCLR0?p=preview。
希望对你有帮助,
蒂埃里
您可以在控件对象中将您的用户名和电子邮件分开,而不是附加到表单中。您将对此有更多的控制权(您可以稍后更新它)。
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);
}
您还可以在加载数据后更新 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 one 中找到控件实例并更新其值。或者简单
this.form.controls.username.updateValue(user.username)
也可以。
UPD. 请注意,在最近的版本中 API 已更改,因此您需要使用 getter:[=14= 访问 username
]
this.form.get('username').setValue(user.username)
使用this.form.setValues({username: this.user.username, mail: this.user.mail})
我有一个使用 Form Builder(Angular2 Beta 1,TypoScript)创建的表单,即:constructor
中有类似这样的内容:
this.form = this._formBuilder.group({
'username': ['', Validators.required],
'email': ['', Validators.required]
});
表格出现了,到目前为止一切都很好。我没有真正了解的是当我从远程服务(或其他一些异步加载机制)加载数据(在本例中为用户对象)时如何处理绑定。
我试过的是:
- 在
constructor
或ngOnInit
中异步加载数据。问题:抛出异常,甚至在加载开始之前(“无法读取 属性 'validator' of undefined …”) - 在
constructor
或ngOnInit
中异步加载数据,但在此之前创建一个空表单。问题:验证不起作用。 - 我期望的工作:将表单数据绑定到
User
对象的属性,并设置该对象的属性。问题:没有异常,但是数据没有显示在表格中。
我想一定有一些 smarter/better 方法可以让它工作?我是 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
的行移动到构造函数的末尾时,它甚至不起作用——这让我感到非常惊讶,因为我希望数据绑定到处理好这个。
我看到了几个解决方案:
- 利用
*ngIf
仅当数据存在时才显示表单 - 利用
@CanActivate
装饰器(如果您使用路由)显示表单所在的组件,仅当数据存在时 - 使用临时空对象与表单绑定。当数据存在时,您可以用收到的数据填充(或覆盖)该对象。
这是一个 plunkr:https://plnkr.co/edit/metUkOB7Sqfyr9DtCLR0?p=preview。
希望对你有帮助, 蒂埃里
您可以在控件对象中将您的用户名和电子邮件分开,而不是附加到表单中。您将对此有更多的控制权(您可以稍后更新它)。
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);
}
您还可以在加载数据后更新 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 one 中找到控件实例并更新其值。或者简单
this.form.controls.username.updateValue(user.username)
也可以。
UPD. 请注意,在最近的版本中 API 已更改,因此您需要使用 getter:[=14= 访问 username
]
this.form.get('username').setValue(user.username)
使用this.form.setValues({username: this.user.username, mail: this.user.mail})