Forms

Input field validity

<input type="text" 
    [(ngModel)]="name"
    required
    #nameRef="ngModel">

<p>{{ nameRef.valid }}</p> // true/false

Display Validation and Error Messaging

<input type="text" 
    [(ngModel)]="name"
    required
    #nameRef="ngModel">

<p>{{ nameRef.errors }}</p> // { required: true }
// #1
<p *ngIf="nameRef.errors?.required">name is required</p>

Create and Submit an Angular 2 Form using ngForm

<form (submit)="saveUpdatePost()" #newPost="ngForm">
    <div class="form-group">
        <label for="title">Title</label>
        <input type="text" class="form-control" id="title" name="title" [(ngModel)]="postData.title">
    </div>
    <div class="form-group">
        <label for="body">Description</label>
        <textarea name="body" id="body" name="body" class="form-control" [(ngModel)]="postData.body"></textarea>
    </div>
    <button type="submit" class="btn btn-primary">
        Add Post
    </button>
</form>

<p>{{ newPost.value }}</p> // { title: '', body: ''}
// overall form validity {{ newPost.valid }}

Quick Note

If you wrap input with ngModel in form it wont's work you need to name attribute for input

Group Inputs with ngModelGroup

<form (submit)="saveUpdatePost()" #newPost="ngForm">
    <fieldset ngModelGroup="address">
        <div class="form-group">
            <input type="text" name="city" ngModel>
        </div>
        <div class="form-group">
            <input type="text" name="state" ngModel>
        </div>        
    </fieldset>
</form>

<p>{{ newPost.value }}</p> // {address: { city: '', state: ''}}

Style validation classes

ng-touched
ng-untouched

ng-valid
ng-invalid

ng-pristine
ng-dirty

Access Form programatically

<form #formRef="ngForm">
</form>
import { ViewChild } '@angular/core';

export class AppComponent{
    @ViewChild('formRef') form;

    ngAfterViewInit(){
        this.form.valueChanges // also try statusChanges
            .subscribe(v => console.log(v));
    }
}

## Handle radio in loop

```javascript
export class AppComponent{
    locations = ['Home', 'Office'];
}
<form #formRef="ngForm">
    <div *ngFor="let location of locations">
        <label [attr.for]="location">{{ location }}</label>
        <input type="radio" [id]="location" ngModel required [value]="location">
    </div>
</form>
<p>{{ formRef.value }}</p> // { location: 'Home' }

Select Dropdown

<form #formRef="ngForm">
    <select name="location" [ngModel]="locations[0]">
        <option [value]="location">{{ location }}</option>
    </select>
</form>
<p>{{ formRef.value }}</p> // { location: 'Home' }

Two way to create form

  • Template driven forms

  • Model driven forms

To use form we must have to import FormsModule or ReactiveFormsModule into the root module

@NgModule({
    imports: [
        'BrowserModule'
        'FormsModule', // template driven forms
        'ReactiveFormsModule' // Model driven forms
    ]
})
export class AppModule {}

Template Driven Form

<form #signupForm="ngForm" (ngSubmit)="registerUser(signupForm)">
    <input type="text" name="email" ngModel>
    <input type="password" name="password" ngModel>
    <button type="submit">Sign Up</button>
</form>
export class SignupFormComponent{
    registerUser(form: NgForm){
        console.log(form.value); // {email: '', password: ''}
    }
}

Nesting form data

Right now form.value returning plain object

{
    email: '',
    password: ''
}

What if we have complex form, and we want to group related fields

{
    contact: {
        firstname: '',
        lastname: ''
    },
    address: {
        city: '',
        street: ''
    }
}
<form #signupForm="ngForm" (ngSubmit)="registerUser(signupForm)">
    <fieldset ngModelGroup="contact">
        <input type="text" name="firstname" ngModel>
        <input type="text" name="lastname" ngModel>
    </fieldset>    
    <fieldset ngModelGroup="address">
        <input type="text" name="city" ngModel>
        <input type="text" name="street" ngModel>
    </fieldset>    
    <button type="submit">Sign Up</button>
</form>

Binding variable to form

One way data binding

<input type="text" name="firstname" [ngModel]="firstname">
<p>{{ firstname }}</p>

Two way data binding

<input type="text" name="firstname" [(ngModel)]="firstname">
<p>{{ firstname }}</p>

Validating template driven form

Template driven form limited to 4 built-in validations

required
minlength
maxlength
pattern
<input type="text" required>
<input type="text" pattern="[a-zA-z0-9]{0,5}">
<input type="text" minlength="3">
<input type="text" maxlength="8">

Last updated

Was this helpful?