MrWolfZ / ngrx-forms

Enhance your forms in Angular applications with the power of ngrx

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Ngrx-Forms With Ngrx/effects.

AlyxEsson opened this issue · comments

Is your feature request related to a problem? Please describe.
I've noticed that there are no direct/easy way to handle actions from ngrx-forms in @ngrx/effects (Or i cant find any at least).
In my case, i've got some actions i want to dispatch from my form but the only way i can do this is to either call dispatch from the component.ts or add a tedious filter for SetValueAction and controlId.

Describe the solution you'd like
I was thinking that having a creator function like ngrx/store ,createEffect, that is similar to ngrx-form's onNgrxFormsAction to be used in @ngrx/effects would be nice. Something like createNgrxFormsEffect.
createNgrxFormsEffect takes in the action type, controlId(optional) and source like in createEffect from @ngrx/effect.

Example:

export class FeatureEffect{
    constructor(private actions$:Actions){}
    effect = createNgrxFormsEffect(SetValueAction, 'form.somevalue',()=> this.actions$.pipe(....), )
}

Additional context
I've made a 'helper' function which does this, but its pretty crude and not very clean (lots of copying code from ngrx/store node-module file to stop the compiler from complaining. But the gist idea is (What i have)

//Bunch of copied types from ngrx/effects such as DispatchType, EffectResult, etc. 
export function createNgrxFormsEffect<C extends EffectConfig, DT extends DispatchType<C>, OT extends ObservableType<DT,OT>, R extends EffectResult<OT>>(
       action: ActionConstructor,
       source: Actions<Action>,
       fn: (source: Actions) => R & ConditionallyDisallowActionCreator<DT, R>,
       controlId?: string,
       config?: Partial<C>
    ): CreateEffectMetadata 
    {
        let s = source.pipe(
            ofType(new (action as any)('', '')),
            filter( (a: any) => a.type === action.TYPE && (controlId !== undefined ? a.controlId === controlId : true)),
	);
        return createEffect(() => fn(s), config);
    }

So i've worked on this a little this 2 days and feel like my original idea above was a little too over worked. I've came up with a simpler solution by just having a ngrxFormsOfType filter to be used in place of ngrx/effects' ofType. I feel that this approach fits how ngrx-forms integrates with ngrx as well.

You can already use ofType like this:

@Effect()
myEffect$: Observable<Action> = this.actions$.pipe(
  ofType<SetValueAction<unknown>>(SetValueAction.TYPE),
  filter(a => a.controlId === 'my.form'),
);

This snippet of code could of course be wrapped in a ngrxFormsOfType function, but I'd prefer to refactor the lib to use proper action creators, that can then be used natively with ofType. Until that happens I think the snippet above is good enough.