Safely Displaying Data with the Elvis Operator

When building Ionic 2 applications, our classes and templates work hand in hand to render the view that the user sees. Our classes are able to define data that we can display in templates through property bindings, and our templates can trigger functions in our classes through event bindings.

If you’re unfamiliar with the concept of interpolation, that is displaying stuff in your templates using {{thisFormat}}, I’d recommend watching this video tutorial first: Component and Template Interaction in Ionic 2.

One common issue in Ionic 2 applications is attempting to display data that does not exist or is not yet defined in the class. Perhaps you are loading some data asynchronously, or are otherwise setting up the data after the view has initially loaded. A common example that we will be looking at in this tutorial is accessing data through a template that is passed in through NavParams.

Typically I would just create an interface for the object I am attempting to display and initialise a blank object so that the template doesn’t complain about not being able to access a property. Another method is to wrap the interpolation in an *ngIf directive and check for the existence of the object before attempting to display it. The worst approach is to just cross your fingers and hope your data loads fast enough so that it is available for the template to display.

I understand that dealing with this situation is necessary, we don’t want templates to just fail silently when we are attempting to access properties that don’t exist, but I’ve never really liked any of the above solutions.

I always thought it was a bit of an awkward situation to deal with until I found out about the Elvis operator, which is this little guy here: ?.. The Elvis operator allows you to check for the existence an object before attempting to access its properties in your interpolations, e.g:

{{someObjectThatMayNotExist?.someProperty}}

This operator is also commonly referred to as the safe navigation operator in other languages and it’s not a concept that is specific to Angular. In fact, the Elvis operator in Angular deviates from the commonly accepted definition as well – Ben Nadel explains this here if you’re interested in the background.

When I finally came across this operator my thinking was – why am I only just learning about this now? – so I figured I’d write a tutorial about it! We will be looking at using the Elvis operator in the context of attempting to access some property on an object in Ionic 2.

Using the Elvis Operator in Ionic 2

Let’s take a look at an example. We’ll take a look at a situation where we grab some data using NavParams inside of the ionViewDidLoad lifecycle hook, and attempt to display it before it is ready.

lesson.ts

import { Component } from '@angular/core';
import { NavController, NavParams } from 'ionic-angular';

@Component({
  selector: 'page-lesson',
  templateUrl: 'lesson.html'
})
export class LessonPage {

    someObject: any;

    constructor(public navCtrl: NavController, public navParams: NavParams) {

    }

    ionViewDidLoad() {
        this.someObject = this.navParams.get('someObject');
    }

}

lesson.html

<ion-header>

  <ion-navbar>
    <ion-title>Lesson</ion-title>
  </ion-navbar>

</ion-header>

<ion-content padding>

    <p>
        {{someObject.someProperty}}
    </p>

</ion-content>

In the code above we would pass some data into the LessonPage and then grab it in the LessonPage by using NavParams. We want to set this data up inside of the ionViewDidLoad lifecycle hook which will run when the view has loaded, but at this point in time, our template which tries to access that data has already attempted to do so. When the template tries to access the data, someObject will still be undefined so we would get the following error:

Ionic 2 Runtime Error
Runtime Error
Error in ./LessonPage class LessonPage - caused by: Cannot read property 'someProperty' of undefined

The interpolation is trying to access a property that doesn’t exist, so naturally, we get an error. It does exist, though, it just doesn’t exist yet.

This is where the Elvis operator comes in. All we would have to do to make the code above work is to change the interpolation in the template to the following:

{{someObject?.someProperty}}

Now instead of telling the template to access someProperty on someObject we are telling it to access someProperty on someObject if someObject exists. So, it first checks if the object exists before trying to run the interpolation. Since Angular has change detection, as soon as that data is loaded then the template will update automatically do display the data.

Summary

Everything we discussed above all happens before a user would even see it happen on screen, but the order in which things happen is important here. The Elvis operator removes a lot of the complexity in this situation, so you can get back to building your application. Thank you very much.

Check out my latest videos: