在角度容器vs redux上管理本地/表单状态

时间:2017-07-17 17:30:23

标签: angular redux ngrx state-management

我现在已经尝试了几种方法来管理组件的表单状态。

对于此示例,我将使用可从下拉列表中选择用户的自定义组件,并使用按钮添加它们,然后在表格行中显示每个用户。每一行都有一个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种不同类型的表单组件,它们在发送之前修改状态。

  • 根本不使用任何redux操作,除了执行SaveUser时,意味着我在表单的初始状态之间没有时间线,直到最后。
  • 仅使用redux意味着我必须进行大量冗长的操作,并为每个操作制作减速器。
  • 像最后一种方法一样使用两者意味着让formControls尽可能多地管理状态,但必须订阅每个单独的用户项,或者我可以听取整个表单,但是使用匹配的FormGroup索引,会使它比必要的更复杂。

0 个答案:

没有答案