AngularJS 2.0 From The Beginning - ngForm Part One - Day Fifteen

I am here to continue the discussion around AngularJS 2.0. So far, we have discussed about data binding, input properties, output properties, pipes, viewchild, Directives, Services including routes in Angular 2.0. Now, in this article, I will discuss how to create template based form, using Angular form module in Angular 2.0. In case, you did not have a look at the previous articles of this series, go through the links mentioned below.

Angular 2.0 Forms – What is it?

In today's Web Application, a large category of front end Applications are very much form dependent, especially in the case of large enterprise type development. Most of these Applications contains simply a huge or large form, which contains multiple tabs, dialogs and with non – trivial business validation logic. Forms are very important of part of the Applications. In a component based Application, we always want to split the forms into a small and reusable piece of code, which is stored within the Smart and Dumb components. These components are normally spread over the entire Application, which provides several architectural benefits including flexibility and design changes.

In Angular 2.0 Framework, we have two different mechanisms, which are related to form-binding. 

  1. Template Driven Form.
  2. Reactive or Model Driven Forms.

In this article, we will discuss about Template Driven Forms.

Angular 2 tackles forms via the famous ngModel. The instantaneous two-way data binding of ng-model in Angular 1 is really a life-saver as it allows to transparently keep in synchronization; a form with a view model. Forms are built with this Directive can only be tested in an end to end test because this requires the presence of a DOM, but still this mechanism is very useful and simple to understand. Unlike the case of AngularJs 1.0, ngModel and other form-related Directives are not available by default, we need to explicitly import them in our Application module. To include the form module in our Application, we need to inject the FormModule in our Application and bootstrapped it. 

Template Driven Forms features

  • Easy to use.
  • Suitable for simple scenarios and fails for complex scenarios.
  • Similar to Angular 1.0.
  • Two way data binding (using [(NgModel)] syntax).
  • Minimal component code.
  • Automatic track of the form and its data.
  • Unit testing is another challenge. 

Advantages and Disadvantages of Template Driven Forms

In this simple example, we cannot really see it, but keeping the template as the source of all form validation truth is something that can become pretty hairy rather than quickly doing it.

As we add more and more validator tags to a field or when we start adding complex cross-field validations the readability of the form decreases to the point, where it will be hard to hand it off to a Web designer.

The up-side of this way of handling forms is its simplicity and its probably more than enough to build a very large range of forms.

On the downside, the form validation logic cannot be unit tested. The only way to test this logic is to run an end to end test with a Browser. For example, using a headless Browser like PhantomJs.

To demonstrate the above concept, we will develop the code given below. For the code, add the files given below with the code.
 
app.component.homepage.html
  1. <h2>Template Driven Form</h2>  
  2. <div>  
  3.     <form #signupForm="ngForm" (ngSubmit)="registerUser(signupForm)">  
  4.         <table style="width:60%;" cellpadding="5" cellspacing="5">  
  5.             <tr>  
  6.                 <td style="width :40%;">  
  7.                     <label for="username">User Name</label>  
  8.                 </td>  
  9.                 <td style="width :60%;">  
  10.                     <input type="text" name="username" id="username" [(ngModel)]="username" required>  
  11.                 </td>  
  12.             </tr>  
  13.             <tr>  
  14.                 <td style="width :40%;">  
  15.                     <label for="email">Email</label>  
  16.                 </td>  
  17.                 <td style="width :60%;">  
  18.                     <input type="text" name="email" id="email" [(ngModel)]="email" required>  
  19.                 </td>  
  20.             </tr>  
  21.             <tr>  
  22.                 <td style="width :40%;">  
  23.                     <label for="password">Password</label>  
  24.                 </td>  
  25.                 <td style="width :60%;">  
  26.                     <input type="password" name="password" id="password" [(ngModel)]="password" required>  
  27.                 </td>  
  28.             </tr>  
  29.             <tr>  
  30.                 <td style="width :40%;"></td>  
  31.                 <td style="width :60%;">  
  32.                     <button type="submit">Sign Up</button>  
  33.                 </td>  
  34.             </tr>  
  35.         </table>  
  36.     </form>  
  37.     <div *ngIf="showMessage">  
  38.         <h3>Thanks You {{formData.username}} for registration</h3>  
  39.     </div>  
  40. </div>   
app.component.homepage.ts
  1. import { Component, OnInit, ViewChild } from '@angular/core';  
  2. import { NgForm } from '@angular/forms';  
  3.   
  4. @Component({  
  5.     moduleId: module.id,  
  6.     selector: 'home-page',  
  7.     templateUrl: 'app.component.homepage.html'  
  8. })  
  9.   
  10. export class HomePageComponent implements OnInit {  
  11.   
  12.     private formData: any = {};  
  13.     private showMessage: boolean = false;  
  14.   
  15.     constructor() {  
  16.     }  
  17.   
  18.     ngOnInit(): void {  
  19.     }  
  20.   
  21.     registerUser(formdata: NgForm) {  
  22.         this.formData = formdata.value;  
  23.         this.showMessage = true;  
  24.     }  
  25. }   
app.module.ts
  1. import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core';  
  2. import { BrowserModule } from '@angular/platform-browser';  
  3. import { FormsModule } from "@angular/forms";  
  4.   
  5. import { HomePageComponent } from './src/app.component.homepage';  
  6.   
  7. @NgModule({  
  8.     imports: [BrowserModule, FormsModule],  
  9.     declarations: [HomePageComponent],  
  10.     bootstrap: [HomePageComponent]  
  11. })  
  12. export class AppModule { }   
index.html
  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4.     <title>Angular2 - Template Driven Form </title>  
  5.     <meta charset="UTF-8">  
  6.     <meta name="viewport" content="width=device-width, initial-scale=1">  
  7.     <link href="../resources/style/bootstrap.css" rel="stylesheet" />  
  8.     <link href="../resources/style/style1.css" rel="stylesheet" />  
  9.     <!-- Polyfill(s) for older browsers -->  
  10.     <script src="../resources/js/jquery-2.1.1.js"></script>  
  11.     <script src="../resources/js/bootstrap.js"></script>  
  12.   
  13.     <script src="../node_modules/core-js/client/shim.min.js"></script>  
  14.     <script src="../node_modules/zone.js/dist/zone.js"></script>  
  15.     <script src="../node_modules/reflect-metadata/Reflect.js"></script>  
  16.     <script src="../node_modules/systemjs/dist/system.src.js"></script>  
  17.     <script src="../systemjs.config.js"></script>  
  18.     <script>  
  19.         System.import('app').catch(function (err) { console.error(err); });  
  20.     </script>  
  21.     <!-- Set the base href, demo only! In your app: <base href="/"> -->  
  22.     <script>document.write('<base href="' + document.location + '" />');</script>  
  23. </head>  
  24. <body>  
  25.     <home-page>Loading</home-page>  
  26. </body>  
  27. </html>  
main.ts
  1. import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';  
  2.   
  3. import { AppModule } from './app.module';  
  4.   
  5. const platform = platformBrowserDynamic();  
  6. platform.bootstrapModule(AppModule); 
Now, run the code and the output is shown below.