Angular 2 + ngrx(redux)+形成

Mar*_*čat 38 forms rxjs redux angular

如何在单向数据流中处理Angular 2表单?特别是在几个父/子组件之间进行验证?

我正在使用ngrx/store和模型驱动的表单与表单构建器.是否可以在React中执行类似于form reducer的操作并将其作为Store的一部分?

你有一些关于它的文章吗?

小智 14

我创建了一个名为ngrx-forms的库,它可以完全满足您的需求.您可以通过以下方式获取:

npm install ngrx-forms --save
Run Code Online (Sandbox Code Playgroud)

我建议在github页面上查看完整的README,但是下面你可以找到一些示例,说明安装后如何启动和运行库.

导入模块:

import { StoreModule } from '@ngrx/store';
import { NgrxFormsModule } from 'ngrx-forms';

import { reducers } from './reducer';

@NgModule({
  declarations: [
    AppComponent,
  ],
  imports: [
    NgrxFormsModule,
    StoreModule.forRoot(reducers),
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
Run Code Online (Sandbox Code Playgroud)

在状态树的某处添加组状态,createFormGroupState并调用formGroupReducerreducer中的内部:

import { Action } from '@ngrx/store';
import { FormGroupState, createFormGroupState, formGroupReducer } from 'ngrx-forms';

export interface MyFormValue {
  someTextInput: string;
  someCheckbox: boolean;
  nested: {
    someNumber: number;
  };
}

const FORM_ID = 'some globally unique string';

const initialFormState = createFormGroupState<MyFormValue>(FORM_ID, {
  someTextInput: '',
  someCheckbox: false,
  nested: {
    someNumber: 0,
  },
});

export interface AppState {
  someOtherField: string;
  myForm: FormGroupState<MyFormValue>;
}

const initialState: AppState = {
  someOtherField: '',
  myForm: initialFormState,
};

export function appReducer(state = initialState, action: Action): AppState {
  const myForm = formGroupReducer(state.myForm, action);
  if (myForm !== state.myForm) {
    state = { ...state, myForm };
  }

  switch (action.type) {
    case 'some action type':
      // modify state
      return state;

    default: {
      return state;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

在组件中公开表单状态:

import { Component } from '@angular/core';
import { Store } from '@ngrx/store';
import { FormGroupState } from 'ngrx-forms';
import { Observable } from 'rxjs/Observable';

import { MyFormValue } from './reducer';

@Component({
  selector: 'my-component',
  templateUrl: './my-component.html',
})
export class MyComponent {
  formState$: Observable<FormGroupState<MyFormValue>>;

  constructor(private store: Store<AppState>) {
    this.formState$ = store.select(s => s.myForm);
  }
}
Run Code Online (Sandbox Code Playgroud)

在模板中设置控件状态:

<form novalidate [ngrxFormState]="(formState$ | async)">
  <input type="text"
         [ngrxFormControlState]="(formState$ | async).controls.someTextInput">

  <input type="checkbox"
         [ngrxFormControlState]="(formState$ | async).controls.someCheckbox">

  <input type="number"
         [ngrxFormControlState]="(formState$ | async).controls.nested.controls.someNumber">
</form>
Run Code Online (Sandbox Code Playgroud)


jpe*_*tte 8

这是一个相当古老的问题,但我无法找到一个很好的解决方案,我自己在Angular中使用ngrx +反应形式.因此,我将在此发表我的研究,希望它可以帮助其他人.我的解决方案可以分为两部分,我祈祷你(风化的灵魂)发现它适用于你的问题:

1)监视表单元素(例如,典型文本输入的"keyup"事件),并从该事件更新State.这种策略来直出的书搜索组件NGRX示例应用程序.我们现在可以在表单更改时成功填充州.真棒!50%完成!

2)角度反应形式指南演示了如何在构造函数中创建表单组.我已经看到其他人在ngOnInit中做了这件事,但是在我们需要的生命周期中为时已晚(我试过,但我失败了).现在我们已经建立了表单组,设置ngOnChanges以捕获从状态推送的任何更改,然后使用patchValue更新表单组.例如:

  ngOnChanges(changes: SimpleChanges) {
    if (changes.valueICareAbout1) {
      this.myForm.patchValue({
        valueICareAbout1: changes.valueICareAbout1.currentValue
      });
    }
    if (changes.valueICareAbout2) {
      this.myForm.patchValue({
        valueICareAbout2: changes.valueICareAbout2.currentValue
      });
    }
  }
Run Code Online (Sandbox Code Playgroud)


Lyi*_*Dog 4

在我使用 Angular 2 构建的应用程序中,以下准则似乎效果很好:

父组件通过数据绑定将数据传递给子组件。子组件通过向父组件发出输出事件来请求数据更改。父组件有责任采取相应的行动。

在分层组件结构中,数据更改由依赖于数据的最低组件处理。如果有另一个更高的组件或依赖于相同数据项的同级组件,则通过发出事件向上传递更改并将处理留给更高的组件。

这一方案效果很好,因为对于与多个组件相关的任何数据,都有一个组件负责执行更改。更改会自动向下冒泡。组件是可重用的,并且可以轻松适应组件树中的更改。

关于验证,梯子中从发出数据更改请求的最低组件到最终处理更改的最高组件之间的任何组件,任何组件都可以通过不向上传递更改来有效地取消更改。在大多数应用程序中,我会选择在更改的源头验证数据更改。

当然,子组件仍然可以具有内部状态并且不需要传达更改 - 除非更改与父组件相关。