abhilash reddy
abhilash reddy

Reputation: 1586

Showing an error message on form submit in angular2?

I have implemented model driven form in this demo. If the user doesn't enter anything and submits the form I am showing an error message using this logic

<div *ngIf="(!myForm.find('sku').valid && submitted)">**sku is required</div>

I am passing a boolean variable 'submitted' to check whether a control is valid or not when submitted. Is there any way to check the state of the control without passing a variable manually? Angular2 forms gives us 6 classes like ng-touched, ng-untouched, ng-valid, ng-invalid, ng-pristine, and ng-dirty. I want to show the error message using only these classes.

Upvotes: 11

Views: 41644

Answers (5)

Bojan
Bojan

Reputation: 186

I know that question is posted a long time ago, but I got the same problem and I wanted to utilize angular control states, so found this working properly:

First I would show error only if control is not pristine:

<span class="help-block" 
      *ngIf="request.get('control').hasError('required') && 
            !request.get('control').pristine">
      This field is required!
</span>

Then you can go trough all controls and mark them as dirty in onSubmit function:

onSubmit() {
//validations
this.form.updateValueAndValidity();
if (this.form.invalid) {
  Object.keys(this.form.controls).forEach(key => {
    this.form.get(key).markAsDirty();
  });
  return;
}

//call function for saving data
this.save(this.form.value);
}

Hope this helps

Upvotes: 11

Chang Liu
Chang Liu

Reputation: 61

I have created the angular 2 version of ng-message.

The syntax is quite similar to ng-message:

<form [formGroup]="formGroup">
    <label for="phoneNumber">Phone Number</label>
    <input type="text" id="phoneNumber" name="phoneNumber" formControlName="phoneNumber" required>
    <cl-ng-messages [control]="formGroup.get('phoneNumber')">
      <template clNgMessage="required">
         This is required
      </template>
      <template clNgMessage="pattern">
        the format of phone number is not correct
      </template>
    </cl-ng-messages>
</form>

https://github.com/changLiuUNSW/ng-messages2

Upvotes: 0

Shawn Palmer
Shawn Palmer

Reputation: 351

I needed to show a validation banner at the top showing all of the form validation errors on submit and only on submit, which sounds like maybe what you were trying to do.

Currently running ng2 beta 17 and the framework does not prevent an invalid form from being submitted. The browser will prevent html validation such as required from being submitted, but any other custom validators do not prevent the form submission.

My approach ended up being to have the validation summary banner handle the form submit with a callback to the parent on success. If the form is invalid the banner shows the summary and does not callback.

Form Setup

<form (ngSubmit)="validationSummary.submit()" [ngFormModel]="myForm">
<div #validationSummary form-validation-summary [form]="myForm" [validSubmitCallback]="validSubmitCallback"></div>
...
<button type="submit" value="SaveButton" class="Button">Save</button>
</form>

Page with form

export class SomeComponent implements OnInit {
    ...
    public validSubmitCallback: Function;
    ngOnInit() {
        this.validSubmitCallback = this.myFormSubmit.bind(this);
    }
    myFormSubmit() {
        alert("a valid form was submitted");
    }
}

Validation Summary

@Component({
    selector: '[form-validation-summary]'
    ...

export class FormValidationSummary {
    @Input() public form: ControlGroup;
    @Input() public validSubmitCallback: Function; 
    ...
    submit() {
        if (this.form.valid) {
            this.validSubmitCallback();
        } else {
            this.formSubmitted = true;
       }
    }
}

Related to adding submit on the form: https://github.com/angular/angular/issues/2960

Upvotes: 0

Thierry Templier
Thierry Templier

Reputation: 202138

I would leverage the pristine and / or touched properties:

  • If you want to display errors after the user fills something in a field, use the pristine property
  • If you want to display errors after the user put the focus on a field, use the touched property

Here is a sample:

<div *ngIf="(!myForm.controls.sku.valid && !myForm.controls.sku.pristine)">
  **sku is required
</div>

Hope it helps you, Thierry

Upvotes: 0

micronyks
micronyks

Reputation: 55443

Yes...

you can check Angular form control's state as show here.

Angular Form Control's Current State

import {Component,View,bind} from 'angular2/core';
import {FORM_DIRECTIVES,CORE_DIRECTIVES,FormBuilder, Validators } from 'angular2/common';
import {bootstrap}        from 'angular2/platform/browser';


@Component({
  selector: 'my-app', 
  template: `
    <h1>LOGIN</h1>


        <form [ngFormModel]="loginForm"  #fm="ngForm"  (submit)="doLogin($event)">

        <input ngControl="name" type="text"  placeholder="Your name" #name="ngForm" required>

        <div [hidden]="name.valid || name.pristine" class="alert alert-danger">Name is required</div>

        <br/>

        <div>Valid ={{name.valid}}</div>
        <div>Pristine ={{name.pristine}}</div>
        <div>Touch ={{name.touched}}</div>

        <BR/><BR/>

        <input ngControl="password" type="password"  placeholder="Your password" #password="ngForm" required>

        <div [hidden]="password.valid || password.pristine" class="alert alert-danger">password is required</div>

        <br/>

        <div>Valid ={{password.valid}}</div>
        <div>Pristine ={{password.pristine}}</div>
        <div>Touch ={{password.touched}}</div>

        <BR/><BR/>

  <button type="submit" [disabled]="!loginForm.valid">Log in</button>

</form>
    `,
  directives: [ROUTER_DIRECTIVES,FORM_DIRECTIVES,CORE_DIRECTIVES]
})

export class Login { 
  constructor(fb: FormBuilder) {
    this.loginForm = fb.group({
      name: ["", Validators.required],
      password: ["", Validators.required]
    });
  }
  doLogin(event) {
    console.log(this.loginForm);
    event.preventDefault();
  }
 }

Don't forget to click the login button to check different objects associated with form in browser's console. Moreover I have tried to bind valid-invalid strip to the textbox which I used to implement in Angular1. I hope this will surely help you.

Upvotes: 2

Related Questions