angulartypescriptangular-reactive-formsangular11

Where to initialise a FormGroup in Reactive forms?


Using Angular 11 with Typescript 4 in Strict Mode I have:

export class ContactComponent implements OnInit { 

  form: FormGroup;

  constructor(private formBuilder: FormBuilder) { }

  ngOnInit() {

    this.form = this.formBuilder.group({ 
      email: ['', [Validators.required, Validators.email]],
      name: ['', [Validators.required, Validators.maxLength(40)]],
    });

  }

I get the build error:

 Property 'form' has no initialiser and is not definitely assigned in the constructor.

Shouldn't the FormGroup be initialised on ngOnInit?


Solution

  • Shouldn't the FormGroup be initialised on ngOnInit?

    It doesn't have to be; I find it simplest to initialize most things directly on the class like this:

    export class ContactComponent implements OnInit { 
    
      form = this.formBuilder.group({ 
        email: ['', [Validators.required, Validators.email]],
        name:  ['', [Validators.required, Validators.maxLength(40)]],
      });
    
      constructor(private formBuilder: FormBuilder) { }
    
    }
    

    This works fine with strictPropertyInitialization.

    The exception is when initializing something that requires data from the DOM (@Input, @ViewChild, etc) Since those things get initialized in the various Lifecycle Hooks as described in this answer:

    Initializing something that depends on say, an @Input(), would be done in the corresponding lifecycle hook, ngOnInit, however, this does not appease the strict rule, so the Definite Assignment Assertion Operator ! is needed.

    export class ContactComponent implements OnInit { 
      @Input() input!: number;
    
      inputDoubled!: number;
      
      form = this.formBuilder.group({ 
        email: ['', [Validators.required, Validators.email]],
        name:  ['', [Validators.required, Validators.maxLength(40)]],
      });
    
      constructor(private formBuilder: FormBuilder) { }
    
      ngOnInit() {
        this.inputDoubled = this.input * 2;
      }
    }