MrWolfZ / ngrx-forms

Enhance your forms in Angular applications with the power of ngrx

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Use the FormControlD directly to update a (nested) state?

schnebdreleg opened this issue · comments

This is more of a question than a feature or bug report.

Currently I have something like this within my reducer:

const enableFormControl = (state: FormState, {controlId}: { controlId: string }) => {
    const attributeKey = findAttributeControlKeyByControlId(state, controlId);

    return updateGroup<FormValue>({
        attributes: (attributeControls) => {
            const updateFns = [] as StateUpdateFns<FormValue['attributes'][];
            updateFns.push({[attributeKey]: enable}); 
            // more modifiers ...
            return updateGroup(attributeControls, updateFns);
        },
    })(state);
};

I use this pattern often within the reducer to apply multiple updates at the same time to a form control (enable, setValue, markAsDirty...). I therefore do not use the actions provided by ngrx-forms, but my own. However, as soon as the form state contains several nested structures, the dynamic determination of the correct "key" in the respective nested control (here, the attributeKey in the nested 'attributes') becomes quite complex.

Is there a way to apply updates with e.g. 'updateGroup' directly by using just the FormControlID provided by an action that I did not see, yet? Something like updateGroup<FormValue>(state, formControlID, updateFns[]) ?

Not out-of-the-box but you can achieve this by using the updateRecursive function.
Although, the main challenge here is gonna be handling the type-safety.
Pseudo-code:

const updateByControlId = (state, formControlId, updateFns[]) => 
    updateRecursive(
      state, 
      s => s.id === formControlId ? 
          updateFns.reduce((finalState, updateFn) => updateFn(finalState), s) : s
    );

Indeed, updateRecursive is the function that you are looking for. If you can't come up with proper types for this function, please post here again and we can do it together.

Thank you for the quick responses. I came across another way last night and I now wonder if that would be equivalent?
Did not know it is possible to use the Actions of ngrx-forms within the reducer:

  let form = state;

  form = formStateReducer(form, new ResetAction(controlId));
  form = formStateReducer(form, new DisableAction(controlId));
  ...
    form = updateGroup<FormValue>({
        attributes: (attributeControls) => {
            const updateFns = [] as StateUpdateFns<FormValue['attributes'][];
            updateFns.push({[attributeKey]: reset});
            updateFns.push({[attributeKey]: disable});
            return updateGroup(attributeControls, updateFns);
        },
    }, )(state);

I've tried the formStateReducer approach in combination with the controlId of a nested form control on the root node of the form state and it seems to be doing the same thing?