Reputation: 1586
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
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
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
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
Reputation: 202138
I would leverage the pristine
and / or touched
properties:
pristine
propertytouched
propertyHere is a sample:
<div *ngIf="(!myForm.controls.sku.valid && !myForm.controls.sku.pristine)">
**sku is required
</div>
Hope it helps you, Thierry
Upvotes: 0
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