BitfulByte
BitfulByte

Reputation: 4456

How to dynamically set 'was-validated' class on form to show validation feedback messages with angular 5 after submit

I am using a template based form in angular. I also use bootstrap (v4) and I wish to show some validation messages when the form was submitted.

This is my form:

<form [ngClass]="{'was-validated': wasValidated}">
  <div class="form-group">
    <label for="name">Name</label>
    <input type="text" id="name" name="name" class="form-control" [(ngModel)]="category.name" #name="ngModel" required maxlength="100"/>
    <div *ngIf="name.invalid" class="invalid-feedback">
      <div *ngIf="name.errors.required">
        Name is required.
      </div>
    </div>
  </div>
  <button type="submit" class="btn btn-success" (click)="save()">Save</button>
</form>

My component looks as follows:

category: Category;

wasValidated: boolean = false;

ngOnInit() {
    this.reset();
}

save() {
    this.wasValidated = true;
    this.categoriesService.createCategory(this.category).subscribe(
        () => {
            this.notificationService.add(notifications.category_saved, {name: this.category.name});
            this.reset();
        },
        () => this.notificationService.add(notifications.save_category_failed)
    );
}

reset() {
    this.wasValidated = false;
    this.category = {} as Category;
}

This works, but I have a feeling it's overly complex and more like a workaround rather than the right way. What is the best way to accomplish this?

Note: the class was-validated must be present on the form element in order to show the div with class invalid-feedback. I'm using this: https://getbootstrap.com/docs/4.0/components/forms/#validation

Note 2: I have currently no mechanism yet to prevent form submission on error. I'd like to know a good solution for that as well!

Upvotes: 0

Views: 2042

Answers (1)

BitfulByte
BitfulByte

Reputation: 4456

With the answer from @Chellappan V I was able to construct the solution I wanted.

I have applied to following changes:

First added #form="ngForm" to the form tag in the template. Secondly I changed the ngClass expression to reference the submitted state of the form, rather than referring to a boolean which was set to true manually when form was submitted. Last but not least I pass the form in the submit method on the save button.

<form novalidate #form="ngForm" [ngClass]="{'was-validated': form.submitted}">
    <!-- form controls -->
    <button type="submit" class="btn btn-success" (click)="submit(form)">Save</button>
</form>

In the component I injected the template variable in the component with @ViewChild.

@ViewChild("form")
private form: NgForm;

The submit method now takes a form parameter of type NgForm which is used to check if the form was valid before sending a request to the backend:

submit(form: NgForm) {
    if (form.valid) {
        this.categoriesService.createCategory(this.category).subscribe(
            () => {
                this.notificationService.add(notifications.category_saved, {name: this.category.name});
                this.reset();
            },
            () => this.notificationService.add(notifications.save_category_failed)
        );
    } else {
        this.notificationService.add(notifications.validation_errors);
    }
}

Finally the reset method resets the form and the model so it can be re-entered to submit a next instance:

reset() {
    this.form.resetForm();
    this.category = {} as NewCategoryDto;
}

Upvotes: 0

Related Questions