10

I have a form as follows :

<form [formGroup]="editProfileForm">
    <input type="text" id="name" class="form-control" placeholder="First" formControlName="firstName [(ngModel)]="profileDetails.first_name">
    <small class="text-danger" [hidden]="editProfileForm.controls['firstName'].valid || (editProfileForm.controls['firstName'].pristine && !submitted)">First name Required</small>
    <input type="text" class="form-control" placeholder="Last" formControlName="lastName" [(ngModel)]="profileDetails.last_name">
    <small class="text-danger" [hidden]="editProfileForm.controls['lastName'].valid || (editProfileForm.controls['lastName'].pristine && !submitted)">Last name Required</small>
    <button class="save-changes-btn" [disabled]="(!editProfileForm.valid)" (click)="saveDetails();">Save Changes</button>
</form>

and the editProfile is defined in the component file as

this.editProfileForm = this.formBuilder.group({
    firstName: [_.get(this.profileDetails, 'first_name', ''), Validators.required],
    lastName: [_.get(this.profileDetails, 'last_name', ''), Validators.required],
});

Now I need to show the validation messages on clicking the submit button. Here now I have disabled the submit button if, the form is not valid. But it will not show the error messages near to the corresponding fields and this will makes the user thinks that the there is nothing happening. How can I trigger the error messages to show near corresponding input fields ?

3 Answers 3

32

When saving, if the form is not valid, simply call markAllAsTouched() on the form group.

saveDetails() {
  if(!this.editProfileForm.valid) {
    this.editProfileForm.markAllAsTouched();
  }
}
Sign up to request clarification or add additional context in comments.

5 Comments

for me this sounds pretty logic.
I logged in only to upvote this answer. This should be marked as answer and proper way to show errors after submit.
Perfect, bingo :)
doesnt work for child components with form from parents
Small side-note: There is also a invalid property on forms which makes reading the code easier: if(this.editProfileForm.invalid) {
14

You can do something like this.

First remove the disabling logic in the submit button.

In component template.

<form [formGroup]="editProfileForm" (ngSubmit)="onSubmit()">
  <div class="form-group block" [ngClass]="{'has-error': submitted && (editProfileForm.controls.firstName.errors)}">
    <label>Email</label>
    <input type="text" class="form-control" formControlName="firstName">
    <p>
      <span *ngIf="submitted && editProfileForm.controls.firstName.errors?.required">First name is required</span>
    </p>
  </div>

  // other controls
</form>

In component class

public onSubmit(): void {
  this.submitted = true;
  if(!this.editProfileForm.valid) {
    return;
  }

  // make the submitted variable false when submission is completed.

}

you can remove following part if you need to.

[ngClass]="{'has-error': submitted && (editProfileForm.controls.firstName.errors)}"

It will add css class to the element when the form control is invalid and submitted.

3 Comments

This construction editProfileForm.controls.firstName.errors?.required is not very well written , since the get() method is used to access form controls, the hasError() method is also used for errors. Better use editProfileForm.get('firstName').hasError('required')
Instead of adding a new property to your class you can add a template variable on your form and use it to check if the form was submitted. This solution is described by this post
thank you ! i was facing that issue and solved it thanks to your answer !
9

Use showValidationMsg() method and pass the form group as parameter inside submit button method:

showValidationMsg(formGroup: FormGroup) {

    for (const key in formGroup.controls) {
        if (formGroup.controls.hasOwnProperty(key)) {
            const control: FormControl = <FormControl>formGroup.controls[key];

            if (Object.keys(control).includes('controls')) {
                const formGroupChild: FormGroup = <FormGroup>formGroup.controls[key];
                this.showValidationMsg(formGroupChild);
            }

            control.markAsTouched();
        }
    }
}

1 Comment

worked perfectly for me with Angular Material and FormGroup. thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.