我现在已经尝试了几种方法来管理组件的表单状态。
对于此示例,我将使用可从下拉列表中选择用户的自定义组件,并使用按钮添加它们,然后在表格行中显示每个用户。每一行都有一个startDate& endDate和一个清除日期的复选框。 然后,发送表格提交。
大致类似于container
:
<user-selector [users]="users$ | async"></user-selector>
<user-row *ngFor="let user of users$ | async">
<input>{{user.startDate}}</input>
<checkbox [value]="user.default"></checkbox>
<input>{{user.endDate}}</divinput
</user-row>
方法1:
调度状态以存储以下单独的组件:
<user-selector>
:
SelectUser(user.id)
AddUser(user.id)
每个ng user-row
:
SetUserDate(user.id, dateType, date)
SetUserDefault(user.id)
container
:
SaveUser(users)
现在我的状态始终处于同步状态,我可以追溯任何以前的状态,并且可以使用redux“time-travel”来查看当我这样做时一切都能正常工作。
也许最混乱的是SetUserDate
,因为它需要这么多的输入来使它工作(dateType是这样我不需要两个单独的动作)
其他的非常简单,减速器确保数据更新。
最后,一个动作SaveUser
接受当前users$
状态并发送异步动作。
方法2:
为每一行创建一个formGroup:
const form = new FormGroup( users: new FormArray(generateGroups(users)));
generateGroups (users: User[]) => {
users.forEach((user: User) => {
return {
startDate: new FormControl(user.startDate),
defaultDate: new FormControl(false),
endDate: new FormControl(user.endDate)
};
});
}
现在只需通过一些ngFor
来形成与示例类似的html。
这里我遇到了一些问题:
startDate
&amp; endDate
至''
。我可以form.valueChanges.subscribe
来听取开始和放大的变化。单独结束或结合最大可能工作。然后修改generateGroups
函数以适应此更改,或直接更新users
对象并再次运行generateGroups
,或执行patchValue
。
我修改组件状态的一个问题是你基本上要修改/更新状态,并避免修改原始状态(除非users
对象已经是克隆,通过使用new User()
模型或只使用{ ...user }
或类似的方法克隆它。
我可以这样做:
addUser(user: User) {
this.users.push(user);
}
类似于删除用户的内容。 但在上面的示例中,我正在修改原始用户对象,如果该用户绑定/引用该存储,则会出现问题,从而直接修改存储。 这将需要一个不同的解决方案:
addUser(user: User) {
let newUsers = { ...this.users };
newUsers.push(user);
return newUsers;
}
然后也应该处理return
值,唯一明智的做法是不做后者,而是坚持前者,并确保已经克隆了this.users
,避免改变国家。通过上述方法,new Users(users)
最有意义。
主要问题
我们最终在Approach 2
做的事情正在做的是减速器所做的事情,但在本地,并且没有任何事件/状态历史记录。
我希望将所需的操作保持在最低限度,我对Approach 1
很好,但是如果表单更大(这可能会导致很多操作) )。这导致我采用第三种方法:
方法3
像第二种方法一样使用formGroups
,然后使用valueChanges
收听个别更改,以便:
form.controls[0].defaultDate.controls.valueChanges.subscribe((changes) => {
// Either dispatch action
this.store.dispatch(new SetUserDefault(this.user.id));
// Or `patchValue`.
form.controls[0].startDate.patchValue('');
form.controls[0].endDate.patchValue('');
});
或者我可以订阅整个表单并找出已经改变的内容,以及采取哪些操作(例如,dispatch或patchValue)以及何时进行操作。 (这听起来像减速机的工作)
最后
这里做的最好的事情是,考虑到这个表单至少有4种不同类型的表单组件,它们在发送之前修改状态。
SaveUser
时,意味着我在表单的初始状态之间没有时间线,直到最后。formControls
尽可能多地管理状态,但必须订阅每个单独的用户项,或者我可以听取整个表单,但是使用匹配的FormGroup
索引,会使它比必要的更复杂。