Angular Reactive Forms, formName.reset() works but throws error 'control.value is null' and all fields are marked 'red' and invalid?

Viewed 4600

I have an angular reactive form and on submit I have this code:

(ngSubmit)="addVideo(); addVidForm.reset();"

I am marking my main form with #addVidForm

I also have some custom validators/controls which is special vs another form that I have where this does not occur when resetting the form.

My validator is as follows:

 static mustBeVimeo(control: AbstractControl) : ValidationErrors | null {

        if((control.value as string).startsWith("https://vimeo.com/")){ return null } else
        if((control.value as string).startsWith("http://vimeo.com/")){ return null }
        else { return { mustBeVimeo : true } }

}

This is my form on the backend:

this.addVideoForm = new FormGroup({
      title: new FormControl('', [Validators.required, Validators.minLength(3), Validators.maxLength(50)]),
      description: new FormControl('', [Validators.required, Validators.minLength(5), Validators.maxLength(200)]),
      category: new FormControl('', [Validators.required]),
      link: new FormControl('', [Validators.required, AddVideoValidators.mustBeVimeo, Validators.maxLength(100)]),
      visibleToGuests: new FormControl(this.visibleToGuests, [Validators.required])
    })

I have also made a function that just resets the form on the backend and call that with a button and I'm getting the same error.

Not entirely sure which part of this whole thing is failing. That field is a normal input like I'm using in other places.

4 Answers

For Reactive Form you need to use [formGroup] attribute Binding. It exposes reset() public method.

Template:

<form [formGroup]="registerForm">
.....
</form>

Component:

this.registerForm.reset();
this.registerForm.markAsPristine();
this.registerForm.markAsUntouched();

You can also pass Empty values to the Form Values.

this.registerForm.reset(this.registerForm.value);

Found another stack overflow thread where in the comments it described what the form.reset() function actually does which is setting all values to nulls instead of their initial values.

I didn't want to manually set the value of each form control upon reset so instead I made a function where I simply re-declare the form on submit. Like this:

  resetForm() {
    this.addVideoForm = new FormGroup({
      title: new FormControl('', [Validators.required, Validators.minLength(3), Validators.maxLength(50)]),
      description: new FormControl('', [Validators.required, Validators.minLength(5), Validators.maxLength(200)]),
      category: new FormControl('', [Validators.required]),
      link: new FormControl('', [Validators.required, AddVideoValidators.mustBeVimeo, Validators.maxLength(100)]),
      visibleToGuests: new FormControl(this.visibleToGuests, [Validators.required])
    })
  }

Had a similar issue(but maybe different root cause), but what works for me is to call reset() with default values:

this.form.reset({
  title: '',
  description: '',
  category: '',
  link: '',
  visibleToGuests: this.visibleToGuests
});

You can check some similar answer at StackOverflow where you store initial values during initialization: https://stackoverflow.com/a/57752522/551256

For me as well was interesting related topic in Angular documentation: https://angular.io/guide/typed-forms#nullability

Create a element reference of your form in your class in the following way.

@ViewChild('formRef') formRef;
form: FormGroup;

In the component class constructor construct your form

constructor() {
  this.form = new FormGroup({
    formControl1: new FormControl()
    // etc...
  })
}

Afterwards add a #formRef to the templates form tag. Pay attention to leave the existing directives as they are.

<form #formRef="ngForm"></form>

Resetting the form is now as simple as

this.form.reset(); // Clears the Angular FormGroup without clearing validators.
this.formRef.resetForm(); // Clears the DOM form with validators

Submitting the form now leads to a cleared form without any validation errors left.

Related