Angular 2: Data Binding and Pipes

Angular 2: Getting Started

4 Data Binding and pipes

1.1 Introduction

We want to bind DOM elements to component properties. Some things that can be done include changing DOM element styles, or responding to user input, like showing or hiding images based on a button click. Sometimes we want both things—set an element property, and receive notifications of changes to that property. That’s two-way binding.

1.2 Property Binding

The first thing we learn is that ng-src has gone the way of all flesh. It’s now: [src] So this:

<img [src]='product.imageUrl'>

is the same as this

<img src='{{product.imageUrl}}'>

And now you know. This is where we left off, where we left a td available for the image in the first column.

                <tr *ngFor='let product of products'>
                    <td>{{ product.productName }}</td>
                    <td>{{ product.productCode }}</td>
                    <td>{{ product.releaseDate }}</td>
                    <td>{{ product.price }}</td>
                    <td>{{ product.starRating }}</td>

And after we add the image URLs and use the product titles for the image titles, it looks like this:

<tr *ngFor='let product of products'>
                    <td><img [src]='product.imageUrl' [title]='product.productName'></td>
                    <td>{{ product.productName }}</td>
                    <td>{{ product.productCode }}</td>
                    <td>{{ product.releaseDate }}</td>
                    <td>{{ product.price }}</td>
                    <td>{{ product.starRating }}</td>

And it works. But the images are very large. So we’ll add image properties directly into the class.

export class ProductListComponent {
    pageTitle: string = 'Product List';
    imageWidth: number = 50;
    imageMargin: number = 2;
    products: any[] = [

Now we use some attributes that are new to us. style.width.px, for instance.

<td><img [src]='product.imageUrl' [style.width.px]='imageWidth' [style.margin.px]='imageMargin' [title]='product.productName'></td>

1.3 Handling Events With Event Binding

Microsoft Word crashed. So whatever was here I’ll just try to summarize. For events, rather than using [something] we use (something) instead. We then call the function. Like (event)='function()'. In the class, the convention is to put functions at the bottom. Methods, I mean. Methods. We don’t need to specify that they’re methods, because the () do it for us. But we do need to specify the return type. In the case we’re about to do, being toggleImage, there is no return, therefore the return type is void.

First things first: we need to create a property that indicates whether images or shown or not.

showImage: boolean = false;

Next, we want to create our toggleImage method.

toggleImage(): void {
    this.showImage = !this.showImage;

On the button:

<button class="btn btn-primary" (click)='toggleImage()'>

Lastly, back on the image we add an *ngIf

<td><img *ngIf='showImage' [src]='product.imageUrl' [style.width.px]='imageWidth' [style.margin.px]='imageMargin' [title]='product.productName'></td>

And it works! Only thing that’s not right is the button always says Show Image. We can use JavaScript interpolation to fix this using a conditional.

<button class="btn btn-primary" (click)='toggleImage()'>
                            {{ showImage ? 'Hide' : 'Show' }} Image

1.4 Handling Input with Two-Way Binding

Two-way binding is, again, when we specify a property in the class that affects something in the DOM, but also is aware of changes in the DOM by the user. This is when we use the ngModel directive. Different than ng-model of a few days ago. This time it gets places in the HTML like this: [(ngModel)]='listFilter'. All the punctuation isn’t arbitrary. [ ] indicates property binding from the class property, just like when we did [src]. And ( ) indicates event binding back to the class property, just like (click). So when you stick them together, now it’s two-way binding.

To remember which order these go in, the tutorial resorts to a dirty picture, [ ( ) ] alongside an even dirtier mnemonic: “banana in a box”. If I said that aloud, or drew that picture, I’d get a detention.

Trying to move past that, let’s remind ourselves that the only way we get to have access to a directive is by pulling it into the app somehow. ngModel is most often used with forms, therefore we can find it in the FormsModule, which we can include in our AppModule to give us access to it.

Back over in the HTML, [(ngModel)]='listFilter', listFilter is a property on the class:

  listFilter: string = 'cart';

“Cart” is just the placeholder value. We’re going to make some changes to this:

            <div>Filter by:</div>


<input type="text" [(ngModel)]='listFilter' />

And also, we use string interpolation here:

                <h3>Filtered by: {{listFilter}}</h3>

The page doesn’t load. Why? Because we haven’t imported the FormsModule. I try to do it myself.

  imports: [ BrowserModule, FormsModule ],

This doesn’t work because it can’t find FormsModule. Because I didn’t import it.

import { FormsModule } from '@angular/platform-browser';

Still doesn’t work because it can’t find it. How am I supposed to find it? I use the tutorial…

import { FormsModule } from '@angular/forms;

Now it loads—and whatever you type in the field shows up in the “filtered by:” thing.

1.5 Transforming Data with Pipes

I’m skipping over stuff about pipes that we learned in our AngularJS course.

Pipes can be used in not only {{interpolation}} but also in [this]=’sort.of | thing’

Currently our product code displays like this: GDN-0023 and our prices like this: 32.99. We’ll change things…

<td>{{ product.productCode | lowercase }}</td>

renders: gdn-0011, duh.


<td>{{ product.price | currency }}</td>

renders: USD32.99

<td>{{ product.price | currency:'USD':true }}</td>

renders: $32.99

<td>{{ product.price | currency:'USD':true:'1.2-2' }}</td>

renders no difference. But what it means is we want at least 1 number to the left of the decimal, and two and only two to the right. By comparison, 3.3-3 would yield: $032.990


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s