WebCake

At the time of this writing, the Ionic 2 docs don’t give much insight into how we can bind data to their ion-checkbox and ion-toggle components. So, I thought I’d go ahead and put up a code example of how I was able to get it working. This demo will load data through an HTTP request, into the view model, and display it using an ion-toggle element.

In this case I’m going to mock out an HTTP request by calling to a JSON file living in the compiled webapp. It will simulate an HTTP call to a backend or local data store, but if you want to dive deeper with your implementation to build a backend, or call to an existing endpoint, go nuts!

Note: This post has been updated from the original subject, which covered a workaround for a bug in an alpha release of Ionic 2. As of alpha.57, ngModel binding works as expected. This post covers how to implement, and has been updated to reflect RC3

Mock JSON

Here’s what my data will look like, located at www/build/js/test.json

{
    "cake": true,
    "cakeIsALie": false
}

Crazy how simple that is. Two booleans to demo loading toggle values. I stored this file in the www/build/js/ so that it could be easily accessed by the index.html file, which will load our single-page app. It can also be stored higher up, in the tree, just as long as it’s accessible from index.html.

Functionality

For simplicity sake, I’m just building straight onto the Page1 class that comes in the ionic start command. I’m also using the TypeScript flavor, which I highly recommend. In any case, you can apply the same principles to your implementation. I’ll break them down into small chunks so they’re easy to understand.

Imports

To start, I’m going to add onto the imports list that comes with a standard Ionic Page:

import {Component} from 'ionic-framework/ionic';
import {Http} from '@angular/http';
import 'rxjs/add/operator/map';

The first one I added was the standard Angular 2 Http class, which we’ll need to make (or in this case mock-out) an HTTP request. The second will allow us to map observable behavior from the request to a property within the Page1 class.

Class declaration

Next we’ll annotate and declare the Page1 class. I’m going to give it two properties. One will be a private property that implements the Http class imported above, and the other will be the data property sent to the template to demo the ion-toggle.

@Component({
    selector: 'page-1',
    templateUrl: 'build/pages/page1/page1.html'
})
export class Page1 {
    public dataObject;
    constructor(private http: Http) {}
}

Keep in mind, TypeScript has that fancy constructor shorthand that creates properties on the class that are passed in as arguments on the constructor. You’ll also notice that although I’m instantiating the dataObject property, it’s not defined. There’s a reason for that, which I’ll get to when we talk about the template.

Making the HTTP request

I’m going to hook into the page lifecycle in order to automatically fire off an HTTP request when the page loads. If you’re interested in learning more about that, I wrote a blog post describing the how and why of the page lifecycle hooks in Ionic 2.

Once the page loads, I’ll make a request to the mock JSON file that I wrote in the beginning of this post. It’ll return data, and map the parsed JSON result (res => res.json()) into the dataObject property that’s passed to the DOM:

export class Page1 {
    public dataObject;
    constructor(private http: Http) {}

    ionViewWillEnter() {
        this.http.get('./build/js/test.json')
            .map(res => res.json())
            .subscribe(
                data => this.dataObject = data,
                err => console.error(err)
        );
    }
}

With that set, it’s time to look at the template, and see how that data is displayed, and how ion-toggle works with ngModel.

The Template

Before we get into implementing ion-toggle, we have to cover the case where an async call hasn’t yet returned data, but the DOM is already rendering. In Angular 1.x apps, we would have handled that with a resolve on the UI-Router config. Not no more, homey. I’m sure we’ll find a way in the coming months to prevent the DOM from loading until all data dependencies have been loaded into the view, but for now we’ll do it with a conditional.

If we had defined the dataObject property when we instantiated it in the Page1 class, the template might have rendered without a value being set for the corresponding properties that power the toggles. So you would have a gotten that flash of an inaccurate view while we waited for the correct data to load.

Anyway, here’s how the template looks as we write that conditional and things begin to take shape:

<ion-navbar *navbar>
    <ion-title>Tab 1</ion-title>
</ion-navbar>

<ion-content padding class="page1">
    <div *ngIf="dataObject">
        <!-- we'll put the stuffs in here... -->
    </div>
</ion-content>

The ion-toggle component has to live inside an ion-item wrapper. On top of that, it’s generally used in concert with an ion-label, which will display accompanying inline text.

Once we add the ion-toggle elements, we’ll add [{ngModel}] attributes to each to map the corresponding booleans to the toggle’s display value. When the bound value evaluates to true, the toggle will be active. When false, it’ll be inactive.

<ion-content padding class="page1">
    <div *ngIf="dataObject">
        <ion-item>
            <ion-label>There will be cake</ion-label>
            <ion-toggle [(ngModel)]="dataObject.cake"></ion-toggle>
        </ion-item>
        <ion-item>
            <ion-label>The cake is a lie</ion-label>
            <ion-toggle [(ngModel)]="dataObject.cakeIsALie"></ion-toggle>
        </ion-item>
    </div>
</ion-content>

At this point, you should be able to load up your project with ionic serve and see one active toggle, and one inactive toggle, corresponding with the two booleans in test.json.

"At the end of the test, you will be baked, and then, there will be cake." “The Enrichment Center is required to remind you that you will be baked, and then there will be cake.”

Testing the toggle-bound data

It’s not enough that we have toggles to prove our data has loaded correctly. We’ll also want to show what’s happening within the view as those toggles are toggled.

Let’s add some text below those toggles to show what happens when we load data, and then when we change the values of those toggles:

<ion-item>
    <p>There will be cake: {{dataObject.cake}}</p>
</ion-item>
<ion-item>
    <p>The cake is a lie: {{dataObject.cakeIsALie}}</p>
</ion-item>

Now, as you turn the toggles on and off, the dataObject values displayed as strings in the template tags will switch between true and false.

Leave a Reply

Your email address will not be published. Required fields are marked *