Angular 2 Ionic 2

Ionic First Look Series: Angular Concepts & Syntax



·

With the introduction of the new versions of the Ionic framework, and the Angular framework that it is built on top of, we are able to make apps that perform better on mobile, adhere to the latest web standards, are scalable, reusable, modular, and so on.

As always, we continue to use the web tech (HTML, CSS, and Javascript) that we know and love to build applications, but there are some conceptual and syntax differences that we need to understand when using Ionic and Angular. For example, the HTML we use looks a little different than you might be used to:

<ion-menu [content]="content">

  <ion-toolbar>
    <ion-title>Pages</ion-title>
  </ion-toolbar>

  <ion-content>
    <ion-list>
      <button ion-item *ngFor="let p of pages" (click)="openPage(p)">
        
      </button>
    </ion-list>
  </ion-content>

</ion-menu>

<ion-nav id="nav" [root]="rootPage" #content swipe-back-enabled="false"></ion-nav>

and the same goes for the Javascript:

import {Component} from '@angular/core';
import {Platform, ionicBootstrap} from 'ionic-angular';
import {StatusBar} from 'ionic-native';
import {HomePage} from './pages/home/home';
import {Data} from './providers/data/data';


@Component({
  template: '<ion-nav [root]="rootPage"></ion-nav>'
})
export class MyApp {
  rootPage: any = HomePage;

  constructor(platform: Platform) {
    platform.ready().then(() => {
      StatusBar.styleDefault();
    });
  }
}

ionicBootstrap(MyApp, [Data]);

If you’re already familiar with ECMAScript 6 or TypeScript then a lot of this probably won’t be too hard of a change for you, but for the rest of us – we’ve got some learning to do.

I’ve already done a bit of an introduction to ECMAScript 6 and Angular 2 for Ionic developers, but in this post I wanted to dive into the actual syntax we will be using in Ionic applications and compare it to how we would have done it in the past (for those of you who may have experience with the original Ionic 1.x version).

Angular & Ionic Concepts

Before I get into the syntax, I wanted to cover a few new concepts you’ll come across when learning Ionic.

Transpiling

Transpiling means converting from one language to another language. Why is this important to us? Basically, ES6 gives us all this new stuff to use, but ES6 is just a standard and it is not completely supported by browsers yet. We use a transpiler to convert our ES6 code into ES5 code (i.e. “normal Javascript”) that is compatible with the browsers of today. Once ES6 is widely supported, this step wouldn’t be necessary.

In the context of Ionic applications, here’s an idea of how it might look:

When we run ionic serve, our code inside of [the app folder] is **transpiled** into the correct Javascript version that the browser understands (currently, ES5). That means we can work at a higher level using TypeScript and ES6+, but compile down to the older form of Javascript the browser needs.
Ionic Website

You don’t need to worry about how this process works, the Ionic CLI will handle everything for you.

Web Components

Web Components are kind of the big thing that is emerging now – they weren’t really feasible to use in Angular 1.x but the next version of Ionic will be entirely based on web components. Web Components are not specific to Angular or Ionic, they are becoming a new standard on the web to create modular, self-contained, pieces of code that can easily be inserted into a web page (kind of like Widgets in WordPress).

In a nutshell, they allow us to bundle markup and styles into custom HTML elements.
Rob Dodson

Rob Dodson wrote a great post on Web Components where he explains how they work and the concepts behind it. He also provides a really great example, and I think it really drives the point home of why Web Components are useful.

Basically, if you wanted to add an image slider as a web component, the HTML for that might look like this:

<img-slider>
  <img src="images/sunset.jpg" alt="a dramatic sunset">
  <img src="images/arch.jpg" alt="a rock arch">
  <img src="images/grooves.jpg" alt="some neat grooves">
  <img src="images/rock.jpg" alt="an interesting rock">
</img-slider>

instead of this:

<div id="slider">
  <input checked="" type="radio" name="slider" id="slide1" selected="false">
  <input type="radio" name="slider" id="slide2" selected="false">
  <input type="radio" name="slider" id="slide3" selected="false">
  <input type="radio" name="slider" id="slide4" selected="false">
  <div id="slides">
    <div id="overflow">
      <div class="inner">
        <img src="images//rock.jpg">
        <img src="images/grooves.jpg">
        <img src="images/arch.jpg">
        <img src="images/sunset.jpg">
      </div>
    </div>
  </div>
  <label for="slide1"></label>
  <label for="slide2"></label>
  <label for="slide3"></label>
  <label for="slide4"></label>
</div>

In the future, rather than downloading some jQuery plugin and then copying and pasting a bunch of HTML into your document, you could just import the web component and add something simple like the image slider code shown above to get it working.

Web Components are super interesting, so if you want to learn more about how they work (e.g. The Shadow Dom and Shadow Boundaries) then I highly recommend reading Rob Dodson’s post on Web Components.

However… you do not need to understand how web components work. Even though the next version of Ionic will use web components behind the scenes, for you it may just be as simple as adding a simple tag:

<ion-card></ion-card>

This is how Ionic works today, we can use custom components and directives through these “made up” HTML tags. By adding these tags to our templates, whatever functionality they provide will be embedded right there. Right now, these are not powered by web components behind the scenes, in future, they will be, but it doesn’t make any difference in the way you use them.

Ionic provides a lot of these pre-made components that we can just drop into our applications to create sleek mobile user interfaces, which is one of the reasons the Ionic framework is so powerful (Ionic does most of the work for us).

Classes

Classes are a concept from Object Oriented Programming. There’s quite a lot to cover on the topic of classes, and I’m not going to attempt to do that here. A good place to start understanding the concept of classes is Introduction to Object-Oriented JavaScript, but keep in mind this is the current (soon to be old) way of implementing objects in JavaScript. JavaScript has never had a class statement, so instead of creating actual classes functions were used to act as classes, but now we will be able to use an actual class syntax with ES6.

In general, a class represents an object. Each class has a constructor which is called when the class is created (this is where you would run some initialisation code and maybe set up some data that the class will hold), and methods that can be called (both from within the class itself, but also by code outside of the class that wants access to something).

We could have a Page object for example. That Page object could store values like title, author and date which could be initialised in the constructor. Then we could add some methods to the class like getAuthor which would return the author of the page, or setAuthor which would change the author.

If you’re familiar with controllers in Angular 1, it’s basically the same thing. In an Angular 1 controller, we can have some code that runs when the controller is created, we store values on $scope which we can access from outside of the controller, and we have a bunch of functions inside of the controller that we can call.

Angular Syntax

Now let’s take a look at some actual Angular syntax that you will be using in your Ionic applications. Before I get into that though, I think it’s useful to know about the APIs that each and every DOM element (that is, a single node in your HTML like <input>) have.

Let’s imagine we’ve grabbed a single node by using something like getElementById(‘myInput’) in JavaScript. That node will have attributes, properties, methods and events.

An attribute is some data you supply to the element, like this:

<input id = "myInput" value = "Hey there">

This attribute is used to set an initial property on the element. Attributes can only ever be strings.

A property is much like an attribute, except that we can access it as an object and we can modify it after it has been created. For example:

var myInput = document.getElementById('myInput');
console.log(myInput.value); // Hey there
myInput.value = "What's up?";
console.log(myInput.value); // What's up?
myInput.value = new Object(); // We can also store objects instead of strings on it

A method is a function that we can call on the element, like this:

myInput.setValue('Hello');

An element can also fire events like focus, blur, click and so on – elements can also fire custom events. If you’d like to know more about the why of the new Angular syntax, and some more theory, I’d recommend reading Angular 2 Template Syntax Demystified by Pascal Precht.

Ok, let’s take a look at some Angular code! There’s a great Angular cheat sheet you can check out here, I’ll be using some examples from there.

Binding a Property to a Value

<input [value]="firstName">

This will set the elements value property to the expression firstName. Note that firstName is an expression, not a string. This means that the value of the firstName variable (defined in your TypeScript file) will be used here, not the literal string ‘firstName’.

Binding a Function to an Event

<button (click)="someFunction($event)">

This will call the someFunction function and pass in the event whenever the button is clicked. You can replace click with any native or custom event you like.

Rendering Expressions with Interpolations

<p>Hi, {{name}}</p>

Just like in Angular 1, this will evaluate the expression and render the result in the template. In this case, it would just display the name variable here, but you can also create other expressions like {{1+1}} which would render 2 in the template.

Two Way Data Binding

In Angular 1.x we could set up two-way data binding by using ng-model, meaning that if we updated a value in our controller the change would be reflected in the template, and if we changed the value in the template it would be reflected in the controller.

We can achieve the same two way data binding in Angular like this:

<input [value]="name" (input)="name = $event.target.value">

This sets the value to the expression name and when we detect the input event we update name to be the new value that was entered. To make this easier, we can still use ng-model in Angular like this to achieve the same thing:

<input [(ngModel)]="name">

This syntax is just a shortcut for the same syntax we described above.

Creating a Template Variable to Access an Element

<p #myParagraph></p>

This creates a local variable that we can use to access the element, so if I wanted to add some content into this paragraph I could do the following:

<button (click)="myParagraph.innerHTML = 'Once upon a time...'">

NOTE: This is just an example to show that you can access the properties of the paragraph tag using the template variable – you shouldn’t actually modify the content of elements using innerHTML in this way.

Structural Directives

<section *ngIf="showSection">

<li *ngFor="let item of items">

We can use structural directives to modify our templates. The *ngIf directive will remove a DOM element if the condition it is attached to is not met. The *ngFor directive can loop over an array, and repeat a DOM element for each element in that array.

Annotations

@Component({
  selector: 'my-component',
  services: [MyService]
})

Annotations like @Component, @Directive and so on allow you to attach information to your components. Max Lynch does a better job of explaining it than I can here. This is also another good explanation.

Import & Export

ES6 allows us to Import and Export components. Take the following component for example:

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

@Component({
  templateUrl: 'hello-ionic.html'
})
export class HelloIonicPage {

  constructor(private navCtrl: NavController) {

  }

}

This component is making use of Component and NavController so it imports them. The HelloIonicPage component that is being created here is then exported.

Now you would be able to access HelloIonicPage by importing it elsewhere:

import { HelloIonicPage } from './pages/hello-ionic/hello-ionic';

It’s a similar concept to Dependency Injection in Angular 1, where we would inject services we were using into the controller like this:

.controller('ExampleCtrl', function($scope, $state, $myService) {

Summary

I will be continuing this post in another part shortly, where we will take a look at some examples specific to Ionic and how this new syntax applies. If you want more information on everything I’ve covered in this post, check out these great resources:

What to watch next...