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

Sync validation of array? #54

Closed
philjones88 opened this issue Mar 23, 2018 · 9 comments
Closed

Sync validation of array? #54

philjones88 opened this issue Mar 23, 2018 · 9 comments

Comments

@philjones88
Copy link
Contributor

I've been digging through the example app and docs but I can't see an example of how to validate an array of objects?

class Item {
  name: string; // Needs to be required
  description: string;
}

class Template {
  name: string;
  items: Item[];
}
@MrWolfZ
Copy link
Owner

MrWolfZ commented Mar 23, 2018 via email

@nihique
Copy link

nihique commented Mar 23, 2018

this is 'stripped out' snippet from our app, where we are validating invoice.payments elements (latter example from MrWolfZ answer):

export interface State {
    form: FormGroupState<Invoice>;
    dateTimeSettings: DateTimeSettings;
}

export interface Invoice extends Entity {
    payments: Payment[];
}

export interface Payment extends Entity {
    invoiceId: number;
    description: string | null;
    amount: number;
}

const FORM_NAME = 'INVOICE_DETAIL_FORM';

const initialForm = createForm(newInvoice(defaultDateTimeSettings), FORM_NAME);

export const initialState: State = {
    form: initialForm,
    dateTimeSettings: defaultDateTimeSettings,
};

const formReducerFn = (dateTimeSettings: DateTimeSettings) =>
    createFormGroupReducerWithUpdate<Invoice>({
        payments: updateArray<Payment>(
            updateGroup<Payment>({
                description: validate(customValidations.required),
                amount: validate([
                    customValidations.required,
                    customValidations.double,
                ]),
            }),
        ),
    });

@philjones88
Copy link
Contributor Author

Pretty much what @nihique said, validate the items in the array but also that there's at least 1 which I managed to figure out myself.

@philjones88
Copy link
Contributor Author

I've tried to copy your example and get:

[ts]
Argument of type '{ name: ProjectFn<AbstractControlState<string>>; blah: ProjectFn<AbstractControlState<string | any...' is not assignable to parameter of type 'FormGroupState<TemplateRole>'.
  Object literal may only specify known properties, and 'name' does not exist in type 'FormGroupState<TemplateRole>'.

with the model:

iterface Template {
  name: string;
  roles: TemplateRole[];
}

interface TemplateRole {
  name: string;
}

with code:

createFormGroupReducerWithUpdate<Template>({
  name: validate<string>(required),
  roles: updateArray<TemplateRole>(
    updateGroup<TemplateRole>({
      name: validate<string>(required)
    })
  )
});

@MrWolfZ
Copy link
Owner

MrWolfZ commented Mar 23, 2018

Yes, the typing for those update functions is a bit sub-optimal. This should do the trick:

createFormGroupReducerWithUpdate<Template>({
  name: validate<string>(required),
  roles: roles => updateArray<TemplateRole>(
    cast(roles),
    updateGroup<TemplateRole>({
      name: validate<string>(required)
    }),
  )
});

With the next version (which I'll release as soon as TypeScript 2.8 is finally released) your version will work due to improved type inference for child controls. I will also clean up the update functions in general to be more consistent.

In regards to combining validation of array items with the whole array you would write the following:

createFormGroupReducerWithUpdate<Template>({
  name: validate<string>(required),
  roles: roles => {
    roles = validate<TemplateRole[]>(minLength(1), roles);
    return updateArray<TemplateRole>(
      cast(roles),
      updateGroup<TemplateRole>({
        name: validate<string>(required)
      }),
    );
  }
});

@philjones88
Copy link
Contributor Author

philjones88 commented Mar 26, 2018

That works thanks.

But.

if you add another property to validate inside the updateArray, updateGroup or add another updateGroup you get the error again. I can't seem to find the right combination to validate multiple properties inside the array:(

@MrWolfZ
Copy link
Owner

MrWolfZ commented Apr 7, 2018

Sorry for the late response. I hope you were able to find the right combination in the meantime. If not, to work around these typing issues (which I am in the process of fixing properly) you can always make the updateGroup or updateArray call explicit by providing an arrow function (Just as I did in my example for the updateArray call. Basically, in my previous example you would adjust the reducer like this:

createFormGroupReducerWithUpdate<Template>({
  name: validate<string>(required),
  roles: roles => {
    roles = validate<TemplateRole[]>(minLength(1), roles);
    return updateArray<TemplateRole>(
      cast(roles),
      // by making the `role` state parameter explicit we ensure that the
      // TypeScript compiler chooses the right overload
      role => updateGroup<TemplateRole>(cast(role), {
        name: validate<string>(required)
      }),
    );
  }
});

@MrWolfZ
Copy link
Owner

MrWolfZ commented Apr 15, 2018

Alright, so in the new and shiny TypeScript 2.8 world the following will type check:

interface Template {
  name: string;
  roles: TemplateRole[];
}

interface TemplateRole {
  name: string;
}

createFormGroupReducerWithUpdate<Template>({
  name: validate(required),
  roles: compose(
    validate<TemplateRole[]>(minLength(1)),
    updateArray(
      updateGroup<TemplateRole>({
        name: validate(required),
      }),
    ),
  ),
});

As far as I know Angular plans to drop TypeScript 2.8 support sometime in May at which point I will also release version 3.0.0 of ngrx-forms. I'll close this issue once that happens.

@MrWolfZ
Copy link
Owner

MrWolfZ commented Jul 22, 2018

I have just released version 3.0.0. The code above should now properly type check.

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

No branches or pull requests

3 participants