Many developers will begin with Angular 2 and reach for something that resembles the trustworthy ng-model
in Angular 1. NgModel
exists in Angular 2, but there is a new way of referencing elements in the template: local template variables.
The code, links, and a live example of this are available at .
Suppose you had the following application and wanted to directly access the input
element:
[app/article.component.ts] import {Component} from '@angular/core'; @Component({ selector: 'article', template: ` <input> <h1>{{title}}</h1> ` }) export class ArticleComponent {}
Angular 2 allows you to have a #
assignment within the template itself, which can consequently be referenced from inside the template. For example, refer to the following code:
[app/article.component.ts] import {Component} from '@angular/core'; @Component({ selector: 'article', template: ` <input #title> <h1>{{title}}</h1> ` }) export class ArticleComponent {}
With this, you will see [object HTMLInputElement]
(or something similar, depending on your browser) interpolated into the <h1>
tag. This means that the #title
inside the <input>
tag is now directly referencing the element object, which of course means that the value of the element should be available for you.
Don't get too excited just yet! If you attempt to interpolate title.value
and then manipulate the input field, you will not see the browser update. This is because Angular 2 no longer supports bidirectional data binding in this way. Fear not, for the solution to this problem lies within the new Angular 2 data binding pattern.
Angular will decline to update the DOM until it thinks it needs to. This need is determined by what behavior in the application might cause the interpolated data to change. A bound event, which will propagate upwards through the component tree, may cause a data change. Thus, you can create an event binding on an element, and the mere presence of this event binding will trigger Angular to update the template:
[app/article.component.ts] import {Component} from '@angular/core'; @Component({ selector: 'article', template: ` <input #title (keyup)="0"> <h1>{{title.value}}</h1> ` }) export class ArticleComponent {}
Here, the keyup
event from the text input is bound to an expression that is effectively a no-op. Since the event will trigger an update of the DOM, you can successfully pull out the latest value
property from the title
input element object. With this, you have successfully bound the input value to the interpolated string.
If you aren't crazy about the #
notation, you can always replace it with val-
and still achieve identical behavior:
[app/article.component.ts] import {Component} from '@angular/core'; @Component({ selector: 'article', template: ` <input val-title (keyup)="0"> <h1>{{title.value}}</h1> ` }) export class ArticleComponent {}
Also, it's important to recall that these template variables are only accessible within the template. If you want to pass them back to the controller, you'll have to use it as a handler argument:
[app/article.component.ts] import {Component} from '@angular/core'; @Component({ selector: 'article', template: ` <input #title (keyup)="setTitle(title.value)"> <h1>{{myTitle}}</h1> ` }) export class ArticleComponent { myTitle:string; setTitle(val:string):void { this.myTitle = val; } }
ViewChild
to reference child component object instancesContentChild
to reference child component object instances