带有 Redux 的 Angular 形式

cga*_*ian 5 forms angularjs redux angular

在使用 Redux 和 Angular 时寻求一些建议。过去几天我一直在研究 Redux,并且确实认为它是存储应用程序数据的好方法。我遇到问题的部分是是否保留商店内的所有内容或仅保留某些部分。理想情况下,我认为整个应用程序应该通过商店运行,但对于表单来说,这似乎非常乏味。

例如,假设我正在使用表单来添加新产品。以下是我的一些痛点。

  • 我想将用户减速器(存储)与实际的表单状态分开。我应该为每个组件创建一个单独的表单减速器吗?

  • 必须将每个输入字段保存回商店听起来工作量很大。我已经看到库redux-form简化了这一点,但它是针对 React 的。

在使用 Redux 在 Angular 中创建表单时,有人有什么好的建议吗?

U A*_*los 4

答案是“这取决于”。另外,假设您确信单向数据流和 redux 的好处,因此如果可以选择,更喜欢 redux 而不是双向数据绑定。

  1. 超级简单的形式(无需验证,与其他状态没有复杂的关系)。然后你可以“裸奔”并直接将输入连接到 redux。在我们的用例中,我们实际上决定使用 Angular 表单,因为我们认为它可以处理边缘情况(IE 和 safari 移动设备)。
  2. 不需要在 redux 状态下进行每个表单更改。然后表单提交可以调度一个动作来更新 redux 状态。如果表单需要根据 redux 状态进行更改,事情就会变得棘手。见下文。
  3. 您确实需要 redux 状态下的每个表单更改。Angular 表单没有 form#ng-change,因此一种策略是将 ng-change 附加到每个调度操作以更新 redux 状态的输入。(是的,这很容易出错,因为很容易忘记使用 ng-change,同时应用程序似乎可以工作。)同样,如果表单需要更改以响应 redux 状态,事情就会变得棘手。见下文。

更新表单以响应 redux 状态更改

常见的用例实际上非常简单。一个具体的例子会有所帮助——假设表单跟踪应用程序设置,同时app settings作为 redux 状态存在。也就是说,Angular 形式和 redux 状态之间存在双向数据绑定。这可能是常见的用例。

在这种情况下,解决方案是像以前一样继续:通过调度更新操作从 Angular 表单更新 redux 状态,并通过 #mapStateToThis 从 redux 状态更新 Angular 表单。

  Angular ----dispatch actions----->  Redux
   Form  <----mapStateToThis--------  State
Run Code Online (Sandbox Code Playgroud)

唯一的问题是不要Redux 状态直接传递给 Angular 表单,即深度克隆数据或使用 ImmutableJS。

另一个常见用例是实现“表单重置”,即在按下按钮后将表单重置为“原始”状态。同样,一个具体的例子会有所帮助:

假设app state(redux state) 通过 flag 跟踪状态是否原始app.pristine。(为了澄清如何app.pristine工作,它按预期工作,也就是说,只要任何值更改,它就会更改为 false,并且仅在显式设置为 true 时才更改为 true。)

首先,据我所知,Angular 不会自动跟踪“初始”状态。你必须自己做,你也可以把这个状态放在 redux 中。app.pristine然后,当为 false时,初始表单值只是应用程序设置。(如果您正在考虑将其放入 #mapStateToThis 中,请不要这样做。在转换函数中执行副作用似乎很奇怪。)更好的方法是使用异步操作,即表单 onChange 侦听器:

// thunk example
onFormChange(newForm) {

  return (dispatch, getState) => {

    const appSettings = getState().appSettings;
    const appIsPristine = appSettings.pristine;

    // this will fire once because the next action will set it to false
    appIsPristine && dispatch(initForm(appSettings)));
    dispatch(updateAppSettings(newForm));
  };
},
Run Code Online (Sandbox Code Playgroud)

重置操作如您所期望的那样工作(我不会概述)。

最后,我应该补充一点,上面假设只有 Angular 表单可以弄脏应用程序设置——否则,初始表单值可能永远不会被存储。如果是这种情况,那么一种惯用的解决方案是创建一个自定义中间件,每当app.pristine更改为 true 时就设置初始表单值。(或者,使用 Angular 手表。)