Building template driven form with latest technique in Angular 2 (Final)

Jecelyn Yeen
Jun 19, 2016 · 4 min read

Last update 2016–07–07: Updated from RC3 to RC4. No code changes.

Last update 2016–06–22: Updated from RC2 to RC3. Control is exported as ngModel, not ngForm anymore

So far, there are two things deprecated before reaching the final Angular 2 release — one is router and the other is form.

There are two ways building form in Angular 2. We’ll talk about the deprecated way and the new and simplified way to build a template driven form in RC 4.

For model-driven forms, please refer to my article here.

We will cover the deprecated way in this article. For the new way, please refer to my Scotch article here.

Live example here:

Scenario: Simple add user form

We will build a really simple form to capture user information based on this interface.

export interface User {
name: string;
address: {
address1?: string;
postcode?: string;
}
}
Add user form

Additional requirements:-

  • User name is mandatory field with minimum 5 characters.
  • Show user name error message only when:-
  • - user name is invalid and it’s dirty (the field is touched/edited)
  • - user name is invalid and the form is submitted

The deprecated way

Here is how our component will look like:-

export class AppComponent {
// keep track on whether form is submitted
public submitted: boolean = false;
// bind default value for demonstrate purpose
public user: User = {
name: ‘John’,
address: {
address1: ’11, High Street’,
postcode: ‘1234’
}
}

// Action when user click on submit button
public save(form: IUser, isValid: boolean) {
this.submitted = true;
console.log(form, isValid);
}
}

Here is how our template form look like.

<form #f=”ngForm” novalidate>
<!-- form control here -->
<button type=”submit” (click)=”save(f.value, f.valid)”>
Submit
</button>
</form>

Notes:-

  1. #f is the reference variable to the form directive. Refer to Angular official documentation for more details.
Layman explanation:
We need a way to retrieve the form data(all the values of our form fields like name, address, postcode, etc). Angular provide us a way, form is exported as ngForm.
We then assign the form data to our local variable f.

2. save function is triggered when form submitted.

Layman explanation:
f.value - an object that refer to the all the form field values.
f.valid - a Boolean that indicates whether the form is valid (e.g. user name field is mandatory. If user name field is not filled, f.valid should be false).

Now, take a look at the user name and address 1 input field:-

...<!-- form control here -->
<div>
<label>Name</label>
<input type=”text”
[(ngModel)]=”user.name” ngControl=”name” #name=”ngForm”
required minlength=”5">
<small [hidden]=”name.valid || (name.pristine && !submitted)”>
Name is required (minimum 5 characters).
</small>
</div>
<div ngControlGroup="address">
<div>
<label>Address</label>
<input type="text"
[(ngModel)]="user.address.address1" ngControl="address1">
</div>
</div>

...

Notes:-

  1. ngModel enable two way binding.
Layman explanation:
In our example, user.name = “John” at the beginning.
"John" will be assigned to the input.
If input value changed to “Jane”,
user.name will be updated to “Jane” accordingly.

2. Use ngControl to track the change state and validity of form control.

Layman explanation:
We need a way to tell <form> that we have a field call "name". ngControl will do that for us.
With ngControl, validators like required, minlength=”5" will work accordingly.For example, our name input is invalid now because the "John" has 4 characters only. Our form is invalid too(f.valid = false).

3. #name is the reference variable to the input directive.

Layman explanation:
Similar to #f, we need a way to read the input data. Angular provide us a way, so happen that input is also exported as ngForm (which is confusing!).
We then assign the input data to our local variable name.With this, we can then use name.pristine, name.valid, etc to check if the name input is dirty, and its validity. We use these values to show/hide the error message.

4. ngControlGroup enables us to semantically group our form controls.

Layman explanation:
Remember at the beginning, we mentioned about the User interface. We want the form submitted value to be something like this:-
{
name: string;
address: {
address1: string;
postcode: string;
}
}
address1 and postcode is under address. To achieve the result above, we need to group our address1 and postcode under address. We use ngControlGroup to achieve this.

The new way

What’s are the changes in new forms module? Please refer to my Scotch article here.


Notes for upcoming RC5 release

According to the form changes proposal, in the coming RC3 release, by default there will be no forms.

To use new forms:

  • Use “provideForms()” function
  • Import any needed symbols from @angular/forms

To use deprecated forms:

  • Use “provideDeprecatedForms()” function
  • Import any needed symbols from @angular/common

However, that’s for RC5.

Jecelyn Yeen

Written by

Coder. Diver. Speak English, Mandarin, Javascript, C# and more.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade