Tutorial

How to Deal with Different Form Controls in Angular 2

Draft updated on Invalid Date
author

Jecelyn Yeen

How to Deal with Different Form Controls in Angular 2

This tutorial is out of date and no longer maintained.

Introduction

In this tutorial we will explore the way to bind these few types of controls to our form: text, number, radio, select (primitive type), select (object), multiple select, checkbox (boolean), and checkbox (toggle value).

Feel free to skip some of the control types (as some of them are really simple).

If you are new to Angular 2 forms, do refer to these articles for basics.

View Angular 2 - Different form controls (final) scotch on plnkr

We will build a form to capture user information based on these interfaces.

user.interface.ts
export interface User {
  name: string; // text
  age?: number; // number
  language?: string; // radio
  role?: string; // select (primitive)
  theme?: Theme; // select (object)
  topics?: string[]; // multiple select
  isActive?: boolean; // checkbox
  toggle?: string; // checkbox toggle either 'toggled' or 'untoggled'
}
theme.interface.ts
export interface Theme {
  display: string;
  backgroundColor: string;
  fontColor: string;
}

Here is how the UI will look:

Angular 2 Form Controls

App Setup

Here’s our file structure:

|- app/
  |- app.component.html
  |- app.component.ts
  |- app.module.ts
  |- main.ts
  |- theme.interface.ts
  |- user.interface.ts
|- index.html
|- styles.css
|- tsconfig.json

In order to use the forms module, we need to npm install @angular/forms npm package and import the forms module in the application module.

  1. npm install @angular/forms --save

Here’s the module for our application app.module.ts:

app.module.ts
import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';

import { AppComponent }   from './app.component';

@NgModule({
  imports:      [ BrowserModule, FormsModule ], // import forms module
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})

export class AppModule { }

The App Component

Let’s move on to create our app component.

app.component.ts
import { Component, OnInit } from '@angular/core';

import { User } from './user.interface';
import { Theme } from './theme.interface';

@Component({
  moduleId: module.id,
  selector: 'my-app',
  templateUrl: 'app.component.html',
  directives: []
})
export class AppComponent implements OnInit {
  public user: User;
  /* standing data goes here*/
  ...
  /* end standing data */
  ngOnInit() {
    // initialize user model here
  }
  public save(isValid: boolean, f: User) {
    console.log(f);
  }
}

Standing Data

We need to include some data for setup as well:

app.component.ts
...

/* standing data goes here*/
public languages = [
  { value: 'en', display: 'English' },
  { value: 'es', display: 'Spanish' }
];
public roles = [
  { value: 'admin', display: 'Administrator' },
  { value: 'guest', display: 'Guest' },
  { value: 'custom', display: 'Custom' }
];
public themes: Theme[] = [
  { backgroundColor: 'black', fontColor: 'white', display: 'Dark' },
  { backgroundColor: 'white', fontColor: 'black', display: 'Light' },
  { backgroundColor: 'grey', fontColor: 'white', display: 'Sleek' }
];
public topics = [
  { value: 'game', display: 'Gaming' },
  { value: 'tech', display: 'Technology' },
  { value: 'life', display: 'Lifestyle' },
];
public toggles = [
  { value: 'toggled', display: 'Toggled' },
  { value: 'untoggled', display: 'UnToggled' },
];
/* end standing data */

...

Initialize model

Then, we need to initialize our user model:

app.component.ts
...

ngOnInit() {
  // initialize user model here
  this.user = {
    name: '',
    language: this.languages[0].value, // default to English
    role: null,
    theme: this.themes[0], // default to dark theme
    isActive: false,
    toggle: this.toggles[1].value, // default to untoggled
    topics: [this.topics[1].value] // default to Technology
  }
}
...

The HTML View

This is how our HTML view will look like.

app.component.html
<form #f="ngForm" novalidate>

  <!-- We'll add our form controls here -->

  <button type="submit" (click)="save(f.value, f.valid)">Submit</button>
</form>

Implementation

Let’s start to look into each type of control.

1. Text

Getting text input is very straightforward. You need the name attribute, and ngModel.

app.component.html
...
<div>
  <label>Name</label>
  <input type="text" name="name" [(ngModel)]="user.name">
</div>

...

2. Number

Getting number input is also very straightforward.

app.component.html
...
<div>
  <label>Age</label>
  <input type="number" name="age" [(ngModel)]="user.age">
</div>

...

3. Radio

Binding radio input is not that easy prior Angular RC 2. With the new form in RC 3 onward, we can directly bind to ngModel, bind the value property.

We have this list of preferred languages:

app.component.ts
public languages = [
  { value: 'en', display: 'English' },
  { value: 'es', display: 'Spanish' }
];

When select, we want only the value Hammerhead or Great White Shark.

app.component.html
...
<div>
  <label>Language</label>
  <div *ngFor="let language of languages">
    <label>
    <input type="radio" name="language" [(ngModel)]="user.language"
    [value]="language.value">
    {{language.display}}
    </label>
  </div>
</div>
...

4. Select (Primitive type)

You can bind select to ngModel. Loop through your option list, set the value property.

We have a list of roles:

app.component.ts

public roles = [
  { value: 'admin', display: 'Administrator' },
  { value: 'guest', display: 'Guest' },
  { value: 'custom', display: 'Custom' }
];

When value selected, we expected it to return string value admin, guest, or custom. Here’s how your HTML will look like.

app.component.html
...
<div>
  <label>Role</label>
  <select name="role" [(ngModel)]="user.role">
    <option *ngFor="let role of roles" [value]="role.value">
    {{role.display}}
    </option>
  </select>
</div>
...

5. Select (object)

Similar to the last example, but this time, instead of a simple type, we want the whole object when it’s selected.

Here is the list of themes:

app.component.ts
public themes: Theme[] = [
  { backgroundColor: 'black', fontColor: 'white', display: 'Dark' },
  { backgroundColor: 'white', fontColor: 'black', display: 'Light' },
  { backgroundColor: 'grey', fontColor: 'white', display: 'Sleek' }
];

When selected, for example Light theme, we expect { backgroundColor: 'white', fontColor: 'black', display: 'Light' } to be returned. Instead of binding to the value property, we bind to ngValue property.

app.component.html
...
<div>
  <label>Theme</label>
  <select name="theme" [(ngModel)]="user.theme">
    <option *ngFor="let theme of themes" [ngValue]="theme">
      {{theme.display}}
    </option>
  </select>
</div>

...

6. Multiple select

We can select more than 1 topics. E.g. when selecting game and tech, it should return ['game', 'tech'].

app.component.ts
public topics = [
  { value: 'game', display: 'Gaming' },
  { value: 'tech', display: 'Technology' },
  { value: 'life', display: 'Lifestyle' },
];

Similar to select, but this time our model is array of string.

app.component.html
...
<div>
  <label>Topics</label>
  <select multiple name="topics" [(ngModel)]="user.topics">
    <option *ngFor="let topic of topics" [value]="topic.value">
      {{topic.display}}
    </option>
  </select>
</div>
...

7. Checkbox (boolean)

By default, checkboxes return boolean. Bind ngModel and define the name attribute as usual.

app.component.html
...
<div>
  <label>
    <input type="checkbox" name="isActive"  [(ngModel)]="user.isActive">
    Is Active
  </label>
</div>

...

8. Checkbox (Toggle value)

In this case, we want to display a checkbox. Instead of boolean, we expecting value. When checked, it should return toggled, else return value untoggled.

This is the list of toggles:

app.component.ts
public toggles = [
  { value: 'toggled', display: 'Toggled' },
  { value: 'untoggled', display: 'UnToggled' },
];

First, we define a hidden input to bind to the real model. Then we create the checkbox input, handle the checked property and change event. Change event fire every time value change, and it has $event that we can read from.

In our case, we read the $event.target.checked to find out if the checkbox is checked, then update model value accordingly.

app.component.html
...
<div>
  <input type="hidden" name="toggle" [(ngModel)]="user.toggle">
  <div>
    <label>
      <input type="checkbox"
        [checked]="user.toggle === toggles[0].value"
        (change)="$event.target.checked? (user.toggle =  toggles[0].value) : (user.toggle = toggles[1].value)">
      {{ toggles[0].display }}
    </label>
  </div>
</div>

...

Tips during development

During development, it’s good that you can visualize the value. Angular provided a very useful json Pipe.

app.component.html
...
<pre>{{your_form or control_name | json }}</pre>

...

Conclusion

That’s it. Hope it helps your journey in Angular 2. Happy coding!

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Jecelyn Yeen

author

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.