FormBuilder with strongly typed form in ng14
Asked Answered
S

3

12

I have the following form:

const enum Fields {
  FirstName = 'firstName',
  LastName = 'lastName'
}

interface FormType {
  [Fields.FirstName]: FormControl<string | null>;
  [Fields.LastName]: FormControl<string | null>;
}

public form!: FormGroup<FormType>;

this.form = new FormGroup({
  [Fields.FirstName]: new FormControl(null, { validators: Validators.required }),
  [Fields.LastName]: new FormControl(null, { validators: Validators.required }),
});

The usage of the enum is an habit I took to avoid mistyping.

When I do this.form.getRawValue().firstName, the type of firstName is correctly defined as string | null. However, I prefer to use the FormBuilder to build my forms but I can't find a way to translate the form above using FormBuilder. I tried this:

this.form = this._fb.group<FormType>({
  [Fields.FirstName]: ['', Validators.required],
  [Fields.LastName]: ['', Validators.required],
});

I could of course use a simple FormGroup without any type but it would defeat the purpose :p

However, this does not even work as the inferred type of string | Validators. I tried different things without success.

Is it possible to use the FormBuilder with the strongly typed forms?

Schaper answered 4/6, 2022 at 15:11 Comment(0)
O
8

For Formbuilder you can provide a raw value, a control, or a boxed value, and the type will be inferred automatically.

this.form = this._fb.group({
  [Fields.FirstName]: ['', Validators.required],
  [Fields.LastName]: ['', Validators.required],
});

Update

We cannot pass type of the model, As FormType expect group with formControl we need to specify formControl to each control.

this.form = this.fb.group<FormType>({
  [Fields.FirstName]: this.fb.control('', Validators.required),
  [Fields.LastName]:  this.fb.control('', Validators.required),
});


this.form.value //value: Partial<{firstName: string | null;lastName: string | null;}>
Overflight answered 4/6, 2022 at 18:19 Comment(1)
I'm so annoyed that the typed forms cannot handle the square bracket syntax!Orelie
M
3

I have a solution for this problem i'm wrote some types for that https://github.com/iamguid/ngx-mf .

For example you can do something like that:

We define some model:

enum ContactType {
    Email,
    Telephone,
}

interface IContactModel {
    type: ContactType;
    contact: string;
}

interface IUserModel {
    id: number;
    firstName: string;
    lastName: string;
    nickname: string;
    birthday: Date;
    contacts: IContactModel[];
}

Then we define some magic type like:

Type Form = FormModel<IUserModel, { contacts: ['group'] }>

Then we have type based on our model before form will be init:

FormGroup<{
    firstName: FormControl<string | null>;
    lastName: FormControl<string | null>;
    nickname: FormControl<string | null>;
    birthday: FormControl<Date | null>;
    contacts: FormArray<FormGroup<{
        type: FormControl<ContactType | null>;
        contact: FormControl<string | null>;
    }>>;
}>
Merengue answered 9/7, 2022 at 17:32 Comment(4)
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From ReviewPlanimetry
@Planimetry i got itMerengue
What is FormModel?Orelie
@FlorestanKorp It is special type to convert object type to FormGroup type, see readme of the library github.com/iamguid/ngx-mfMerengue
T
2

@Chellappan small addition:
at least you can strictly give the types in here and not inferring from the provided value by introducing a type specifically.

FormBuilder example:

this.form = this.fb.group<FormType>({
  [Fields.FirstName]: this.fb.control<string|null>(null, Validators.required),
  [Fields.LastName]:  this.fb.control<string|null>(null, Validators.required),
});

So by using form methods like setValue shouldn't result in an error when providing strings even if it's initialized with null

See also: https://angular.io/guide/typed-forms#specifying-an-explicit-type

Triplicity answered 7/10, 2022 at 14:23 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.