Angular 2 Input Binding Tutorial

Bind to the following <input> fields with Angular 2 and TypeScript: text, textarea, checkbox, radio and select (drop-down list).

Text

We use two-way data binding with ngModel to bind to the textValue property on the component class.

Two-way binding allows us to use the property to set the initial value of an <input>, and then have the user's changes flow back to the property. We can also change the property value in the code and have these changes reflected in the <input>. For more information about two-way data binding with an input field, see the Angular 2 Two Way Data Binding tutorial.

A template reference variable on the input gives us access to the properties and methods of the input control.

text.component.ts
import { Component } from '@angular/core';

@Component({
    selector: 'text-box',
    template: `
        <h1>Text ({{textValue}})</h1>
        <input #textbox type="text" [(ngModel)]="textValue" required> 
        <button (click)="logText(textbox.value)">Update Log</button>
        <button (click)="textValue=''">Clear</button>
        
        <h2>Template Reference Variable</h2>
        Type: '{{textbox.type}}', required: '{{textbox.hasAttribute('required')}}',
        upper: '{{textbox.value.toUpperCase()}}'
        
        <h2>Log <button (click)="log=''">Clear</button></h2>
        <pre>{{log}}</pre>`
})
export class TextComponent {

    private textValue = "initial value";
    private log: string ='';

    private logText(value: string): void {
        this.log += `Text changed to '${value}'\n`
    }
}

The Application

Here is the output from this component.

Text Area

textarea behaves in a similar way to the textbox. Again, we use two-way data binding with ngModel to bind to the textValue property on the component class to keep user and programmatic changes in sync.

This time we use the canonical form to specify the template reference variable but we could just as easily used #textarea instead.

text-area.component.ts
import { Component } from '@angular/core';

@Component({
    selector: 'text-area',
    template: `
        <h1>Text Area</h1>
        <textarea ref-textarea [(ngModel)]="textValue" rows="4"></textarea><br/>
        <button (click)="logText(textarea.value)">Update Log</button>
        <button (click)="textValue=''">Clear</button>
        
        <h2>Log <button (click)="log=''">Clear</button></h2>
        <pre>{{log}}</pre>`
})
export class TextAreaComponent {

    private textValue = "initial value";
    private log: string ='';

    private logText(value: string): void {
        this.log += `Text changed to '${value}'\n`
    }
}

The Application

Here is the output from this component.

Checkbox

The change event is triggered when the user clicks on a checkbox. We use this event to pass a template reference variable into a function to log user action. We can determine whether or not the checkbox has been selected using the checked property of the argument.

We also use the checked property to highlight the selected checkbox labels using class bindings. This uses the styles property to set the text color to OrangeRed for all the selected checkboxes.

checkbox.component.ts
import {Component} from '@angular/core';

@Component({
    selector: 'checkbox',
    template: `
        <h1>Checkbox</h1>
        <p>
            <label [class.selected]="cb1.checked">
                <input #cb1 type="checkbox" value="one" (change)="logCheckbox(cb1)"> One
            </label>
            <label [class.selected]="cb2.checked">
                <input #cb2 type="checkbox" value="two" (change)="logCheckbox(cb2)"> Two
            </label>
            <label [class.selected]="cb3.checked">
                <input #cb3 type="checkbox" value="three" (change)="logCheckbox(cb3)"> Three
            </label>
        </p>
        
        <h2>Log <button (click)="log=''">Clear</button></h2>
        <pre>{{log}}</pre>`,
    styles: ['.selected {color: OrangeRed;}']
})
export class CheckboxComponent {

    private log: string ='';

    private logCheckbox(element: HTMLInputElement): void {
        this.log += `Checkbox ${element.value} was ${element.checked ? '' : 'un'}checked\n`
    }
}

The Application

Here is the output from this component.

Radio

The radio field behaves in a similar way to the checkbox. We use the change event on the <input> element to execute a template statement which passes a template reference variable into a component method.

The value property property of the HTMLInputElement argument is used to log user's selection. This value property corresponds to the value attribute of the HTML <input> element.

radio.component.ts
import {Component} from '@angular/core';

@Component({
    selector: 'radio',
    template: `
        <h1>Radio</h1>
        <p>
            <label [class.selected]="r1.checked">
                <input #r1 type="radio" name="r" value="one" (change)="logRadio(r1)"> One
            </label>
            <label [class.selected]="r2.checked">
                <input #r2 type="radio" name="r" value="two" (change)="logRadio(r2)"> Two
            </label>
            <label [class.selected]="r3.checked">
                <input #r3 type="radio" name="r" value="three" (change)="logRadio(r3)"> Three
            </label>
        </p>
        
        <h2>Log <button (click)="log=''">Clear</button></h2>
        <pre>{{log}}</pre>`,
    styles: ['.selected {color: OrangeRed;}']
})
export class RadioComponent {

    private log: string ='';

    private logRadio(element: HTMLInputElement): void {
        this.log += `Radio ${element.value} was selected\n`
    }
}

The Application

Here is the output from this component.

Drop-down List

We use an array to populate the drop-down with a list of values. The built-in ngFor directive comes in handy here to loop through the array and set up the option values. For more information on ngFor or any other of the built-in directives see the Angular 2 Built-in Directives tutorial.

[(ngModel)] sets up two-way data binding on the select element. This will ensure that the drop-down list will display the current item when it is opened. When a new value is chosen from the list, two-way binding also ensures that the current property on the component is automatically updated.

An additional binding to the change event of the select element logs the user action by calling a method in the template statement.

drop-down.component.ts
import {Component} from '@angular/core';

@Component({
    selector: 'drop-down',
    template: `
        <h1>Drop-down List</h1>
        <select #select [(ngModel)]="current" (change)="logDropdown(select.value)">
            <option *ngFor="let item of list" [value]="item.id">{{item.name}}</option>
        </select>
        
        <h2>Log <button (click)="log=''">Clear</button></h2>
        <pre>{{log}}</pre>`
})
export class DropDownComponent {

    private list = [
        { id: 1, name: 'one' },
        { id: 2, name: 'two' },
        { id: 3, name: 'three' }
    ];
    private current: number = 2;
    private log: string ='';

    private logDropdown(id: number): void {
        const NAME = this.list.find( (item: any) => item.id == id ).name;
        this.log += `Value ${NAME} was selected\n`
    }
}

The Application

Here is the output from this component.

Where Next?

To find out more about Angular and TypeScript, check out these tutorials.

  • Hello World - Implement a super-simple <hello-world> custom element using an Angular and TypeScript.
  • The Angular with TypeScript Tutorial - includes examples of components, template syntax, property binding, event binding, bootstrapping and more.
  • Configuration - Configure Angular and TypeScript to download dependencies from node modules or a CDN, and to compile the TypeScript during development or in the browser at runtime.
  • Templates - introduction to inline and external templates.
  • Interpolation - use curly braces and template expressions to output data on the page.
  • Property Binding - bind to DOM properties using square brackets and template expressions.
  • Event Binding - handle DOM events using parentheses and template statements.
  • Two-way Binding - combine property and event binding to create two-way binding with ngModel.
  • Built-in Directives - see how to use built-in directives ngIf, ngSwitch, ngFor, ngClass and ngStyle.
  • Component Input Output - use @Input and @Output to pass data in to and out of a component.
  • Angular Router - Use the Angular router to navigate between components when the user clicks a link.
  • Nested Child Routes - An example of how child routes allow navigation between multiple views when a user clicks a link in a sub-menu.