在 ngrx 成功操作后如何清理我的表单?

How can I clean my form after a ngrx succeeded action?

我有反应形式:

const createFormGroup = (dataItem?: Usuario) => {
  if (dataItem) {
    return new FormGroup({
      id: new FormControl(dataItem.id),
      nome: new FormControl(dataItem.nome),
      cidade: new FormControl(dataItem.cidade)
    });
  }
  return new FormGroup({
    id: new FormControl(),
    nome: new FormControl(''),
    cidade: new FormControl('')
  });
};

这是我的模板:

<form (ngSubmit)="save()" [formGroup]="formGroup">
   <input formControlName="nome" type="text" class="form-control" id="inputName" placeholder="Nome">
   <input formControlName="cidade" type="text" class="form-control" id="exampleInputPassword1"
   <button id="my-element" type="submit" class="btn btn-primary">Complete
   </button>
</form>

单击 "submit" 后,我使用 ngrx 效果进行了一次保存数据的调度:

save() {
  const user = this.formGroup.value;
  if (user.id === null) {
    this.store.dispatch(createUser({ user: user }));
  } else {
    this.store.dispatch(updateUser({ user: user }));
  }
}

这是我的效果:

public saveUser$ = createEffect(() =>
  this.actions$.pipe(
    ofType(createUser),
    switchMap((action) =>
      this.usuarioService.save(action.user).pipe(
        map(() => loadUsers()),
        catchError((error) => of(loadUsers()))
      )
    )
  )
);

有人可以告诉我是否有一种方法可以在我的效果没有进入 catchError 时清除我的反应?

使用This.formGroup.reset()根据要清除表单值的条件重置表单

  • 如果您想以 ngrx 方式执行此操作,请根据您的效果调用另一个操作以确保成功。
saveUser$ = createEffect(() =>
    this.actions$.pipe(
        ofType(createUser),
        switchMap((action) =>
            this.usuarioService.save(action.user).pipe(
                map(() => {
                    loadUsers();
                    return new clearFormAction();
                }),
                catchError((error) => of(loadUsers()))
            )
        )
    )
);
  • clearFormAction().
  • 的 reducer 中将表单数据重置为空(一般情况下为初始状态)
case clearFormAction: {
    return {
        ...state,
        id: '',
        nome: '',
        cidade: ''
    };
}
  • 在您的组件 ngOnInit() 中订阅商店表单数据
this.storeFormData$ = this.store.select(formData);
this.storeFormData.subscribe(formData => {
    this.formGroup.setValue(formData);
});
  • 因此,只要您的 this.usuarioService.save() 成功,您的表格就会被清除。

如果您只想在确定操作已成功分派后清除表单,我会设置一个简单的服务,其中包含一个可观察对象,当 this.usuarioService.save 成功时,该对象会由您的效果更新:

效果:

您需要将 Subject 导入您的效果文件:

import { Subject } from 'rxjs';

然后添加如下服务。这可以在一个单独的文件中,但为了简单起见,将它添加到效果文件的顶部,紧挨着所有 "imports"

@Injectable({
  providedIn: 'root'
})
export class ClearFormService {
  private clearFormSource = new Subject<boolean>();
  clearForm$ = this.clearFormSource.asObservable();
  clearForm() {
    this.clearFormSource.next(true);
  }
}

接下来,将此服务添加到您的效果中的构造函数中 class:

constructor(private clearFormService: ClearFormService) { }

如果您的构造函数中已经有引用,请添加:

private clearFormService: ClearFormService

...到最后。

您可以在 this.usuarioService.save 成功后更新此服务中的可观察对象。注意大括号已添加到 map。有 'more rxjs' 种方法,但我认为这很好:

public saveUser$ = createEffect(() =>
  this.actions$.pipe(
    ofType(createUser),
    switchMap((action) =>
      this.usuarioService.save(action.user).pipe(
        map(() => {
            this.clearFormService.clearForm(); // Updates your service
            return loadUsers();
        }),
        catchError((error) => of(loadUsers()))
      )
    )
  )
);

具有表单的组件:

然后在带有表单的组件中,您需要从效果文件中导入 ClearFormService 并将其添加到构造函数中,与在效果文件中所做的相同。您可能还需要导入 subscription:

import { Subscription } from 'rxjs';

然后您可以订阅 clearForm$,并在收到回复时清除表单。

clearFormSubscription = new Subscription();

ngOnInit() {
    this.clearFormSubscription = this.clearFormService.clearForm$.subscribe(response => {
        this.formGroup.reset()
        console.log('Clear Form Here');
    })
  }

不要忘记取消订阅 onDestroy!

ngOnDestroy() {
    this.clearFormSubscription.unsubscribe()
}

您可以设置一个使用您的 ngrx 商店的解决方案,但我认为这会过度设计。

也许只是观察组件中的状态,如果特定 属性 指示操作已成功执行,则进行所有重置。

ngOnInit(): void {
    this.watchOperations();
    // ...
}

watchOperations(): void {
    this.store
    .pipe(
        select(state => state.todos.succeeded)
    )
    .subscribe(succeeded => {
        if (succeeded) {
            this.store.dispatch(LOAD());
            this.formSubmitted = false;
            this.form.reset(this.formDefaults);
        }
    });
}

说到效果:

createEffect(() => this.actions$.pipe(
    ofType(ADD),
    mergeMap(({ payload }) => {
      return this.todosService.add(payload)
        .pipe(
          map(() => ({ type: '[Todos] Add Success' })),
          catchError(() => of({ type: '[Todos] Add Fail' }))
        );
    })
));

组件:

addTodo(): void {
    this.formSubmitted = true;

    if (this.form.valid) {
        this.store.dispatch(ADD({
            payload: {
                ...this.form.value,
                done: false
            } as ITodo
        }));
    }
}

和减速器:

// ...
on(ADD, (state, action) => {
    return {
        ...state,
        processed: action.payload,
        processing: true
    };
}),
on(ADD_SUCCESS, (state) => {
    return {
        ...state,
        processing: false,
        succeeded: true
    };
}),
on(ADD_FAIL, (state) => {
    return {
        ...state,
        processing: false,
        succeeded: false
    };
}),
// ...