Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
schnebdreleg opened this issue Dec 1, 2021 · 3 comments
Open

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

schnebdreleg opened this issue Dec 1, 2021 · 3 comments

Comments

@schnebdreleg
Copy link

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[]) ?

@dzonatan
Copy link
Contributor

dzonatan commented Dec 1, 2021

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
    );

@MrWolfZ
Copy link
Owner

MrWolfZ commented Dec 2, 2021

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.

@schnebdreleg
Copy link
Author

schnebdreleg commented Dec 2, 2021

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants