Lesson 4: Decorators

Each class (which we will talk about in the next section) you see in an Ionic application will have a decorator. A decorator looks like this:

@Component({
    someThing: 'somevalue',
    someOtherThing: [Some, Other, Values]
})

They definitely look a little weird, but they play an important role. Their role in an Ionic application is to provide some metadata about the class you are defining, and they always sit directly above your class definition (again, we'll get to that shortly) like this:

@Decorator({
    /*meta data goes here*/
})
export class MyClass {
    /*class stuff goes here*/
}

This is the only place you will see a decorator, they are used purely to add some extra information to a class (i.e. they "decorate" the class). So let's talk about exactly how and why we would want to use these decorators in an Ionic application.

The decorator name itself is quite useful, here's a few you might see in an Ionic application:

We can supply an object to the decorator to provide even more information on what we want. Here's the most common example you'll see in your applications:

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

}

Now this class knows where it needs to fetch its template from, which will determine what the user will actually see on the screen (we'll be getting into that later as well). If you've got a super simple template, maybe you don't even want to have an external template file, and instead define your template like this:

@Component({
    selector: 'page-home',
    template: `<p>Howdy!</p>`
})
export class HowdyPage {

}

Some people even like to define large templates using template. Since ES6 supports using backticks (the things surrounding the template above) to define multi-line strings, it makes defining large templates like this a viable option if you prefer (rather than doing something ugly like concatenating a bunch of strings).

Now that we've covered the basics of what a decorator is and what it does, let's take a look at some specifics.

Common Decorators in Ionic 2 Applications

There are quite a few different decorators that we can use. In the end, their main purpose is simply to describe what the class we are creating is, so that it knows what needs to be imported to make it work.

Let's discuss the main decorators you are likely to use, and what the role of each one is. We're just going to be focusing on the decorator for now, we will get into how to actually build something useable by defining the class in the next section.

@Component

I think the terminology of a component can be a little confusing in Ionic. As I mentioned, our application is made up of a bunch of components that are all tied together. These components are contained within folders inside of our main src folder, and they look like this:

home

A @Component is not specific to Ionic, it is used generally in Angular 2. A lot of the functionality provided by Ionic is done through using components. In Ionic, for example, you might want to create a search bar, which you could do by using one of the components that Ionic provides like this:

<ion-searchbar></ion-searchbar>

You simply add this custom tag to your template. Ionic provides a lot of components but you can also create your own custom components, and the decorator for that might look something like this:

@Component({
    selector: 'my-cool-component'
})

which would then allow you to use it in your templates like this:

<my-cool-component></my-cool-component>

NOTE: Technically speaking a component should have a class definition and a template. Things like pipes and providers aren't viewed on the screen so have no associated template, they just provide some additional functionality. Even though these are not technically components you may often see them referred to as such, or they may also be referred to as services or providers.

@Directive

The @Directive decorator allows you to create your own custom directives. Typically, the decorator would look something like this:

@Directive({
    selector: '[my-selector]'
})

Then in your template you could use that selector to trigger the behaviour of the directive you have created by adding it to an element:

<some-element my-selector></some-element>

It might be a little confusing as to when to use @Component and @Directive, as they are both quite similar. The easiest thing to remember is that if you want to modify the behaviour of an existing component use a directive, if you want to create a completely new component use a component.

@Pipe

@Pipe allows you to create your own custom pipes to filter data that is displayed to the user, which can be very useful. The decorator might look something like this:

@Pipe({
  name: 'myPipe'
})

which would then allow you to implement it in your templates like this:

<p>{{someString | myPipe}}</p>

Now someString would be run through your custom myPipe before the value is output to the user.

@Injectable

An @Injectable allows you to create a service for a class to use. A common example of a service created using the @Injectable decorator, and one we will be using a lot when we get into actually building the apps, is a Data Service that is responsible for fetching and saving data. Rather than doing this manually in your classes, you can inject your data service into any number of classes you want, and call helper functions from that Data Service. Of course this isn't all you can do, you can create a service to do anything you like.

An @Injectable will often just look like a normal class with the @Injectable decorator tacked on at the top:

@Injectable()
export class DataService {

}

IMPORTANT: Remember that just about everything you want to use in Ionic needs to be imported first (we will cover importing in more detail in the next section). In the case of pipes, directives, injectables and components they not only need to be imported, but also declared in your app.module.ts file. We will get into the specifics around this when we go through the application examples.

@IonicPage

The @IonicPage decorator works in tandem with the NavController to help provide navigation, and "lazy load" pages. It is included by default at the top of any "page" that is generated in your application, but it is worth noting that a "page" is nothing more than a normal @Component. Adding the @IonicPage decorator just builds a little more functionality into this @Component.

One of the primary benefits of using the @IonicPage decorator is that it enables you to "lazy load" pages. The basic concept of lazy loading is loading something only when you need it. This concept is often used with images on a website, where not all images on the page are loaded at once, just the ones the user can currently see. It's a similar concept in an Ionic application, rather than loading every page in the application at startup, lazy loaded pages will only load when required. This can help speed up the start up time of your application.

The process for lazy loading a page involves create a "module" for that page. We already discussed before that a class decorated with a @NgModule (which is just another kind of decorator) is used to set up the dependencies that our application requires like the various components and services so that we don't have to import them everywhere we need them. We aren't limited to just having one module defined like the root module in app.module.ts, though, we can create as many as we want.

The process for lazy loading pages is quite easy, because most of the work is done for you when you generate a page with Ionic's ionic generate command. All you would need to do is include the automatically generated module for the page in your root module in app.module.ts. However, I will briefly go over how you would go through this process manually.

First, you would need to create a module for the page you want to lazy load, like this:

src/pages/lazy-load/lazy-load.module.ts

import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { LazyLoad } from './lazy-load';

@NgModule({
  declarations: [
    LazyLoad,
  ],
  imports: [
    IonicPageModule.forChild(LazyLoad),
  ],
  exports: [
    LazyLoad
  ]
})
export class LazyLoadModule {}

This sets up the module for a page called LazyLoad. As you can see, this is pretty similar to the module in app.module.ts (just a bit simpler).

We also need to make sure that we add the @IonicPage decorator to the component:

src/pages/lazy-load/lazy-load.ts

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

@IonicPage()
@Component({
  selector: 'page-lazy-load',
  templateUrl: 'lazy-load.html',
})
export class LazyLoad {

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

  ionViewDidLoad() {
    console.log('ionViewDidLoad LazyLoad');
  }

}

When lazy loading pages we should not include them in the declarations and entryComponents arrays in app.module.ts like we do with normal pages. We also do not even need to import the page itself anymore. Elsewhere in the application, you would also no longer need to import the page to use it, it will just be available by default (which is pretty cool!). Without lazy loading you would have to import the LazyLoad page, and then reference it wherever you want to use it as LazyLoad. With lazy loading, you do not need to import the page where you want to use it, and instead you just provide the pages name as a string, i.e. 'LazyLoad'.

The @IonicPage decorator is also used to enable deep linking in an application, which allows you to open specific pages in your application by using a URL.

Summary

The important thing to remember about decorators is: there's not that much to remember. Decorators are powerful, and you can certainly come up with some complex looking configurations. Your decorators may become complex as you learn more about Ionic, but in the beginning, the vast majority of your decorators will probably just look like this:

@IonicPage()
@Component({
  selector: 'home-page',
  templateUrl: 'home.html'
})

I think a lot of people find decorators off putting because at a glance they look pretty weird, but they look way scarier than they actually are. In the next lesson we'll be looking at the decorator's partner in crime: the class. The class definition is where we will do all the actual work, remember that the decorator just sits at the top and provides a little extra information.

Copyright © 2016 Joshua Morony | Privacy Policy | Contact

This is a preview of Building Mobile Apps With Ionic 2 LEARN MORE