3

I have below code where I just submit few details and reset the form after successful submission.

ngOnInit() {
    this.initContactForm();    
}

initContactForm(){
    this.contactForm = this.formBuilder.group({
            fullname: ['', Validators.compose([Validators.required, Validators.minLength(2), Validators.maxLength(30)])],
            email: ['', Validators.compose([Validators.required])],
            phone: ['', Validators.compose([Validators.required, Validators.minLength(10), Validators.maxLength(12)])],
            subject: ['', Validators.compose([Validators.required, Validators.maxLength(25), Validators.minLength(5)])],
            message: ['', Validators.compose([Validators.required, Validators.minLength(10), Validators.maxLength(200)])]
        });
}

onSubmit(model){
    if (this.contactForm.valid){
        this.contactModel = model;
        this.dataService.sendContactMessage(this.contactModel).then((resp) => {
            if (resp){
                this.openSnackBar('Message has been sent', 'Done');    
                this.contactForm.reset();
                this.contactForm.updateValueAndValidity();
                this.contactForm.setErrors(null);
            }else{
                console.log('Error');
            }

        });
    }else{
        alert('Invalid form');
    }
}

View

<form autocomplete="off" [formGroup]="contactForm" novalidate (ngSubmit)="onSubmit(contactForm.value)">
    <div class="row">
        <div class="col m4 s12">
            <mat-form-field>
                <input oninput="javascript: if (this.value.length > this.maxLength) this.value = this.value.slice(0, this.maxLength);" maxlength="30" matInput type="text" placeholder="Full Name" value="" name="fullname" formControlName="fullname" required>
                <mat-error *ngIf="contactForm.controls['fullname'].hasError('required')">
                    <strong>Please enter your Fullname</strong>
                </mat-error>
            </mat-form-field>
         </div>
         <div class="col m4 s12">
            <mat-form-field>
                <input matInput type="email" placeholder="Email Address" value="" name="email" formControlName="email" required email>
                <mat-error *ngIf="contactForm.controls['email'].hasError('required')">
                     <strong>Please enter your Email Id</strong>
                </mat-error>
            </mat-form-field>
         </div>
         <div class="col m4 s12">
            <mat-form-field>
                <input matInput type="tel" placeholder="Contact Number" value="" name="contact" formControlName="phone" required tel>
                <mat-error *ngIf="contactForm.controls['phone'].hasError('required')">
                    <strong>Please enter your Contact number</strong>
                 </mat-error>
            </mat-form-field>
        </div>
    </div>
    <div class="clearfix"></div>
    <div class="row">
        <div class="col m12 s12">
            <mat-form-field>
                <input matInput type="text" oninput="javascript: if (this.value.length > this.maxLength) this.value = this.value.slice(0, this.maxLength);" maxlength="25" placeholder="Subject" value="" name="subject" formControlName="subject" required>
                <mat-error *ngIf="contactForm.controls['subject'].hasError('required')">
                    <strong>Please enter Subject</strong>
                </mat-error>
             </mat-form-field>
        </div>
        <div class="col s6 s12">
            <mat-form-field>
                <textarea matInput type="text" style="resize:none;" oninput="javascript: if (this.value.length > this.maxLength) this.value = this.value.slice(0, this.maxLength);" maxlength="200" placeholder="Message" value="" name="message" formControlName="message"
                rows="5" required></textarea>
                <mat-error *ngIf="contactForm.controls['message'].hasError('required')">
                    <strong>Please enter your Message</strong>
                </mat-error>
            </mat-form-field>
        </div>
     </div>
     <div class="row margin-top20">
        <div class="col l6 push-l6 s12 right-align">
            <button type="submit" mat-button class="btn btn-primary">Send</button>
        </div>
        </div>
</form>

Whenever I call contactForm.reset() values get cleared but all the errors show up again.

I've tried various other ways to clear this as below:

  • Tried calling initContactForm() after form reset

  • Tried looping through each form control and used markAsUntouched(), markAs Pristine() etc.,

Here it is

Object.keys(this.contactForm.controls).forEach(key => {
    this.contactForm.controls[key].setErrors(null);
    this.contactForm.controls[key].updateValueAndValidity();
});

Am I left with anything else to try. I am still not able to clear the errors after reset.. Hope to get some help.

Guruprasad J Rao
  • 29,410
  • 14
  • 101
  • 200

2 Answers2

2

As soon as you reset the form, values are cleared.

Validators.required will then be processed and your field will become invalid as it is empty. If you want to show errors only when user has interacted with the form control, add this to your conditions:

mat-error *ngIf="contactForm.controls['phone'].hasError('required') && contactForm.controls['phone'].dirty"
Grégory Elhaimer
  • 2,731
  • 1
  • 16
  • 21
  • 1
    Nope bro.. Even though the error message isn't displayed, the control is still invalid.. :( – Guruprasad J Rao Mar 11 '18 at 11:51
  • 1
    And its normal as your `Validators.required` will return an error. You'll see that at the very beginning, before any interaction, your form is already invalid. – Grégory Elhaimer Mar 11 '18 at 11:52
  • But even though I set `form.setErrors(null)` and `form.updateValueAndValidity()` still form has errors. How come.. :( – Guruprasad J Rao Mar 11 '18 at 11:58
  • Once again: it's normal. You can't bypass form's validation workflow. When you use `form.updateValueAndValidity()`, then validation is processed and errors are set. `form.setErrors(null)` works only if you manage the whole form's validation manually. – Grégory Elhaimer Mar 11 '18 at 12:01
  • Try just NOT TO CALL updateValueAndValidity() function after clearing errors – Andriy Mar 11 '18 at 12:14
  • `updateValueAndValidity()` is called before clearing errors. It still won't change the issue, as automatic validation is set through the formBuilder, then `setErrors(null)` manually will have no effects – Grégory Elhaimer Mar 11 '18 at 12:17
  • So, what's the ultimate way to overcome this? Now even though error message is not displayed, control will be invalid and a red underline will be displayed under control. How can I overcome this? – Guruprasad J Rao Mar 11 '18 at 15:15
  • Change the CSS to display the red line only when the input is both invalid and dirty. Angular decorates the input with such classes (like ng-invalid etc) – Grégory Elhaimer Mar 13 '18 at 13:07
0

Try adding this after you reset your form

    this.contactForm.markAsPristine();
    this.contactForm.markAsUntouched();
    this.contactForm.updateValueAndValidity();
raxerz
  • 516
  • 4
  • 10