FormGroup中依赖表单控件的初始化
Initialization of dependent form controls in FormGroup
有一个表单组,其中一些表单控件值依赖于其他表单控件值。在我的特定情况下,它们也相互依赖,但为简单起见,下面的示例中未显示这一点。
这是一个plunk。
const fetchedFormValues = {
timestamp: '1504116487374'
};
Observable.from(this.form.get('timestamp').valueChanges)
.filter(v => v)
.distinctUntilChanged()
.subscribe(timestamp => {
console.log('timestamp', timestamp);
this.form.get('date').setValue(new Date(timestamp).toISOString().substr(0, 10));
this.form.get('time').setValue(new Date(timestamp).toISOString().substr(11, 12))
});
this.form.reset(fetchedFormValues);
初始表单值从后端获取并使用 reset
设置(这也可以稍后完成)。问题是 date
和 time
的 setValue
在 timestamp
更改时工作正常,但在重置时被忽略。
我尽量让它保持干燥,并避免在多个地方使用 this.form.get('date').setValue...
,因为这已经在列出的可观察对象中完成了。
为什么 date
和 time
表单控件不受 reset
上的 timestamp
订阅的影响? reset
行为是否可以修复以接受 setValue
所做的更改?是否有任何其他方法来处理(相互)依赖的表单控件?
FormGroup 的 reset()
函数如下所示:
FormGroup.prototype.reset = function (value, options) {
if (value === void 0) { value = {}; }
if (options === void 0) { options = {}; }
this._forEachChild(function (control, name) {
control.reset(value[name], { onlySelf: true, emitEvent: options.emitEvent });
});
this.updateValueAndValidity(options);
this._updatePristine(options);
this._updateTouched(options);
};
在您的情况下 this._forEachChild
将 return 按顺序控制:
- 时间戳
- 日期
- 时间
当时间戳字段被设置时,它的 valueChanges
被触发并且其他两个字段被正确填充,但是随后这两个字段被 [= 再次设置为 undefined
(value[name]
) 17=] 次迭代。
因此,最快的解决方法是将您的字段顺序更改为:
this.form = this.fb.group({
date: null,
time: null,
timestamp: null
});
这样 date
和 time
字段将设置为 undefined
然后在最后一次迭代中 'timestamp' 字段将被填充并更改值 date
和 time
个字段。
另一个(我更喜欢的)解决方案是使用 patchValue
函数,而不是 reset
。 patchValue
函数看起来像:
FormGroup.prototype.patchValue = function (value, options) {
var _this = this;
if (options === void 0) { options = {}; }
Object.keys(value).forEach(function (name) {
if (_this.controls[name]) {
_this.controls[name].patchValue(value[name], { onlySelf: true, emitEvent: options.emitEvent });
}
});
this.updateValueAndValidity(options);
};
它只迭代提供给函数的字段,而不是控件。因此,在您的情况下,只有 timestamp
字段将被更新并触发其 valueChanges
事件发射器。
所以而不是
this.form.reset(fetchedFormValues);
写
this.form.patchValue(fetchedFormValues);
使用 patchValue
您还可以控制 valueChanges
发射器的触发。如果你不想 valueChanges
被触发(这不是你的情况),你可以写:
this.form.patchValue(fetchedFormValues, {emitEvent: false});
参考代码来源:https://unpkg.com/@angular/forms@4.3.6/bundles/forms.umd.js
有一个表单组,其中一些表单控件值依赖于其他表单控件值。在我的特定情况下,它们也相互依赖,但为简单起见,下面的示例中未显示这一点。
这是一个plunk。
const fetchedFormValues = {
timestamp: '1504116487374'
};
Observable.from(this.form.get('timestamp').valueChanges)
.filter(v => v)
.distinctUntilChanged()
.subscribe(timestamp => {
console.log('timestamp', timestamp);
this.form.get('date').setValue(new Date(timestamp).toISOString().substr(0, 10));
this.form.get('time').setValue(new Date(timestamp).toISOString().substr(11, 12))
});
this.form.reset(fetchedFormValues);
初始表单值从后端获取并使用 reset
设置(这也可以稍后完成)。问题是 date
和 time
的 setValue
在 timestamp
更改时工作正常,但在重置时被忽略。
我尽量让它保持干燥,并避免在多个地方使用 this.form.get('date').setValue...
,因为这已经在列出的可观察对象中完成了。
为什么 date
和 time
表单控件不受 reset
上的 timestamp
订阅的影响? reset
行为是否可以修复以接受 setValue
所做的更改?是否有任何其他方法来处理(相互)依赖的表单控件?
FormGroup 的 reset()
函数如下所示:
FormGroup.prototype.reset = function (value, options) {
if (value === void 0) { value = {}; }
if (options === void 0) { options = {}; }
this._forEachChild(function (control, name) {
control.reset(value[name], { onlySelf: true, emitEvent: options.emitEvent });
});
this.updateValueAndValidity(options);
this._updatePristine(options);
this._updateTouched(options);
};
在您的情况下 this._forEachChild
将 return 按顺序控制:
- 时间戳
- 日期
- 时间
当时间戳字段被设置时,它的 valueChanges
被触发并且其他两个字段被正确填充,但是随后这两个字段被 [= 再次设置为 undefined
(value[name]
) 17=] 次迭代。
因此,最快的解决方法是将您的字段顺序更改为:
this.form = this.fb.group({
date: null,
time: null,
timestamp: null
});
这样 date
和 time
字段将设置为 undefined
然后在最后一次迭代中 'timestamp' 字段将被填充并更改值 date
和 time
个字段。
另一个(我更喜欢的)解决方案是使用 patchValue
函数,而不是 reset
。 patchValue
函数看起来像:
FormGroup.prototype.patchValue = function (value, options) {
var _this = this;
if (options === void 0) { options = {}; }
Object.keys(value).forEach(function (name) {
if (_this.controls[name]) {
_this.controls[name].patchValue(value[name], { onlySelf: true, emitEvent: options.emitEvent });
}
});
this.updateValueAndValidity(options);
};
它只迭代提供给函数的字段,而不是控件。因此,在您的情况下,只有 timestamp
字段将被更新并触发其 valueChanges
事件发射器。
所以而不是
this.form.reset(fetchedFormValues);
写
this.form.patchValue(fetchedFormValues);
使用 patchValue
您还可以控制 valueChanges
发射器的触发。如果你不想 valueChanges
被触发(这不是你的情况),你可以写:
this.form.patchValue(fetchedFormValues, {emitEvent: false});
参考代码来源:https://unpkg.com/@angular/forms@4.3.6/bundles/forms.umd.js