Smithy
Smithy

Reputation: 847

Form input validation in Angular 2(template driven)

I would like to make these inputs to display a message such as "Name is required" when submitted(so the submit button is disabled until there is name inside). Is there perhaps a simple way to do it with Angular 2 Template Driven forms? I guess that I should provide some properties in form's HTML, and connect it to a component, but could not figure it out while following the samples in documentation. Appreciate all the help.

<form class="">
    <div>
        <p>Name:</p>
        <input type="text">
    </div>
    <div class="link-input">
        <p>City:</p>
        <input type="text">
    </div>

    <button 
        (click)="submitForm()">
        Submit
    </button>
</form>

Upvotes: 3

Views: 6367

Answers (4)

Malhari
Malhari

Reputation: 155

The angular 2 form validation quite differs than what we have done in angular 1. when you write form tag to the DOM angular 2 adds the ngForm and ngControl to it. A button can be disabled by using angular2 property [disabled]. to keep button disabled you need to apply validation property to [disabled]. I have given one simple example which will give you form validation, input fields validation with pattern validation. the button will be disabled until the form will be valid

In your HTML

<form [formGroup]="myForm" (ngSubmit)="submitForm(myForm.value)">
  <div class="form-group" [ngClass]="{'has-error':!signinForm.controls['usermail'].valid && signinForm.controls['usermail'].touched}">
      <label>Email Address</label>
      <input class="form-control" type="email" [formControl]="signinForm.controls['usermail']">
      <span *ngIf="signinForm.controls['usermail'].hasError('required') && signinForm.controls['usermail'].touched && !signinForm.submitted" class="required pull-right">*Please Enter Email</span>
      <span *ngIf="signinForm.controls['usermail'].hasError('pattern') && signinForm.controls['usermail'].touched" class="required pull-right">*Invalid Email</span>
    </div>
    <div class="form-group" [ngClass]="{'has-error':!signinForm.controls['userpass'].valid && signinForm.controls['userpass'].touched}">
       <label>Password</label>
       <input class="form-control" type="password" [formControl]="signinForm.controls['userpass']" (focus)="showErrorMessage=false">
        <span *ngIf="signinForm.controls['userpass'].hasError('required') && signinForm.controls['userpass'].touched && !signinForm.submitted" class="required pull-right">*Please Enter Password</span>
    </div>
      <button type="submit" class="btn btn-pri mds_btn" [disabled]="!signinForm.valid">Login</button>       
</form>

In your Component

import { Component } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { Router } from '@angular/router';

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: [ './login.component.scss' ]
})
export class LoginComponent {
   myForm: FormGroup;

   emailRegex: any = '^[a-z0-9]+(\.[_a-z0-9]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,15})$';
    passRegex:any ='^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,}$'; 

   constructor(fb: FormBuilder) {

      this.myForm = fb.group({
         'logmail': [ null, Validators.compose([ Validators.required, Validators.pattern(this.emailRegex) ]) ],
         'logpass': [ null, Validators.compose([ Validators.required, Validators.pattern(this.passRegex) ]) ]
      });

    this.myForm.valueChanges.subscribe((form: any) => {
   });
  }

  submitForm(lgvalue: any) {
       //do logic here after submitting the form

  }
}

in this example, I am using FormGroup directive of FormBuilder.The FormBuilder creates instances of FormGroup, which we refer to as a form. I am also subscribing to the form so that whenever the value entered in the input field the form will be subscribed.

I hope this will help you :)

Upvotes: 2

Devansh
Devansh

Reputation: 1267

TEMPLATE DRIVEN FORMS

I also having this question and i found answer and that i wanted to share with you. I created a login form with validation which is look like as following:

login.component.html

<div class="col-md-6 col-md-offset-3">
    <h2>Login</h2>
    <form name="form" (ngSubmit)="f.form.valid && login()" #f="ngForm" novalidate>
        <div class="form-group" [ngClass]="{ 'has-error': f.submitted && !username.valid }">
            <label for="username">Username</label>
            <input type="text" class="form-control" name="username" [(ngModel)]="model.username" #username="ngModel" required />
            <div *ngIf="f.submitted && !username.valid" class="help-block">Username is required</div>
        </div>
        <div class="form-group" [ngClass]="{ 'has-error': f.submitted && !password.valid }">
            <label for="password">Password</label>
            <input type="password" class="form-control" name="password" [(ngModel)]="model.password" #password="ngModel" required />
            <div *ngIf="f.submitted && !password.valid" class="help-block">Password is required</div>
        </div>
        <div class="form-group">
            <button [disabled]="loading" class="btn btn-primary">Login</button>
            <img *ngIf="loading" src="loading.gif" />
            <a [routerLink]="['/register']" class="btn btn-link">Register</a>
        </div>
    </form>
</div>

login.component.ts

import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';

import { AlertService, AuthenticationService } from '../services';

@Component({
    templateUrl: './login.component.html'
})

export class LoginComponent implements OnInit {
    model: any = {};
    loading = false;
    returnUrl: string;

    constructor(
        private route: ActivatedRoute,
        private router: Router,
        private authenticationService: AuthenticationService,
        private alertService: AlertService) { }

    ngOnInit() {}

    login() {
        this.loading = true;
        this.authenticationService.login(this.model.username, this.model.password)
            .subscribe(
                data => {
                    this.router.navigate([this.returnUrl]);
                },
                error => {
                    this.alertService.error(error);
                    this.loading = false;
                });
    }
}

I hope this will help you if you need any help you can write me. I feel happy to help you. @Smithy i am also learning angular 2.

Upvotes: 3

SeleM
SeleM

Reputation: 9638

Your Html :

<form role="form" [formGroup]="inputForm" novalidate>
    <div>
        <p>Name:</p>
        <input
         formControlName="name"
         type="text">
    </div>
    <div class="link-input">
        <p>City:</p>
        <input
         formControlName="city"
         type="text">
    </div>

    <button 
        [disabled]="!inputForm.valid"
        (click)="submitForm()">
    </button>
</form>

Your Component:

import { FormGroup, FormBuilder, FormControl, Validators } from '@angular/forms';

export class InputComponent  {   
   public inputForm: FormGroup;
  constructor(private formBuilder: FormBuilder) {

  this.inputForm = this.formBuilder.group({
  name:    new FormControl('', Validators.required),
  city:    new FormControl('', Validators.required),
   });
  }
//... codes..
}

Upvotes: 3

Nate May
Nate May

Reputation: 4062

This makes sure that that the form has been touched (inputs have been changed) and that the name field is at least 1 letter long. You can do something similar for city.

Component:

import { FormGroup, FormBuilder, FormControl, Validators } from '@angular/forms';

export class InputComponent  {   
  public inputForm: FormGroup;
  constructor(private formBuilder: FormBuilder) {

    this.inputForm = this.formBuilder.group({
      name:    new FormControl('', Validators.required, Validators.minLength(1)]),
      city:    new FormControl('', Validators.required),
    });
  }
}

View:

<form [formGroup]="inputForm" novalidate>
  <p>Name:</p>
  <input placeholder="Exercise" formControlName="name">
  <div class="errorMsg" *ngIf="inputForm.get('name').touched && inputForm.get('name').status === 'INVALID'">
    Name is required</div>
  <p>City:</p>
  <input placeholder="Exercise" formControlName="city">
  <button [disabled]="!inputForm.valid || !inputForm.touched (click)="submitForm()">Submit</button>
</form>

Upvotes: 2

Related Questions