Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typed Angular form with formbuilder and null as initial value

I want to make use of typed forms in Angular.
In my scenario I have a form group that should have some properties.
All of them should be nullable and start with an initial value of "null".
But they should also be typed.

I also want to use the form builder to make my code short & concise.

However, I am failing to do what I want.

One of my approaches looks like this:

   formGroup = this.fb.group<{
      User: FormControl<string | null>,
      Site: FormControl<string | null>,
      AccessLevel: FormControl<string | null>,
      Application: FormControl<string | null>,
      BusinessProcessArea: FormControl<string | null>,
    }>({
      User: [null, Validators.required],
      Site: [null, Validators.required],
      AccessLevel: [null, Validators.required],
      Application: [null, Validators.required],
      BusinessProcessArea: [null, Validators.required],
   });

However, typescript does not like what I am doing and throws an error here.
Also I need to double all the properties what makes this piece of code also hard to maintain.

I would love to do something like this:

   formGroup = this.fb.group({
      User<string>: [null, Validators.required],
      Site<string>: [null, Validators.required],
      AccessLevel<string>: [null, Validators.required],
      Application<string>: [null, Validators.required],
      BusinessProcessArea<string>: [null, Validators.required],
   });

I know that this is not valid Typescript and that I cannot put the type definition there.

But this should show my wish to:

  • Allow nullable fields
  • That are at the same time typed fields (ie: string|null)
  • That do not need to be repeated
  • That can use form builder to have a concise and clear syntax

How can I achieve this?

like image 877
David Mason Avatar asked May 13 '26 23:05

David Mason


1 Answers

I find that defining an interface for my typed forms gives me a clearer syntax overall. An example is given below:


// person-form.model.ts

export interface IPersonForm {
    firstName: FormControl<string | null>;
    lastName: FormControl<string | null>;
    identifier: FormControl<string | null>;
}

// person-form.component.ts

@Component({
    selector: 'app-person-form',
    standalone: true,
    imports: [],
    templateUrl: './person-form.component.html',
    styleUrl: './person-form.component.scss',
})
export class PersonFormComponent
    implements OnInit
{
   
    private fb = inject(FormBuilder);
    public personForm!: FormGroup<IPersonForm>;

    ngOnInit(): void {
      this.buildForm()
    }

    private buildForm(): void {
      this.personForm = this.fb.group({
        firstName: [null, [Validators.required]],
        lastName: [null, [Validators.required],
        identifier: [null, [Validators.maxLength(255)]],
      });
    }

       


Additionally, unless you have a specific need for null I would recommend typing the controls as string only and defining the initial value as empty string - this is a 'falsy' value and will trigger the required validator correctly without the use of null.

like image 97
Sam Scholefield Avatar answered May 15 '26 17:05

Sam Scholefield



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!