Ionic applications rely heavily on the concept of modules, which is functionality that was introduced in the ES6 specification for Javascript. Technically, Ionic applications use TypeScript syntax not just plain ES6, but TypeScript is just an extension of ES6 so the concept is the same.
To put everything into context, the Javascript that developers have been working with over the past few years has been based on the ES5 specification. This specification did not include support for creating modular code with classes, which is pretty important for a programming language, so people found ways to work around this. The ES6 specification does support classes, so now we can create modules that we can define in one file, and then import that functionality somewhere else in our application.
Even though we are able to make use of these ES6 features right now, ES6 is not widely supported by browsers. The code we write is actually transpiled into the equivalent ES5 code so that it will run properly in browsers, but we don’t need to worry about that because we can just use ES6 features and the Ionic build process will handle this transpiling for us.
In this tutorial, we are going to take a look at how we make use of ES6 modules in an Ionic application and how exactly they work.
How ES6 Modules Work
Before getting into more detailed examples that are specific to Ionic, I want to really quickly cover the basic idea of a module (because I think it is simpler than my introduction might make it sound). Here it is:
Step 1: Export a class, function, or variable
some-file.ts
export function sayHello() {
console.log('hello!');
}
Step 2: Import and use that module elsewhere
someOtherFile.ts
import { sayHello } from '../path/to/some-file';
sayHello(); // This will log 'hello!' to the console
That’s pretty much the whole concept. You export things which makes them available to import elsewhere in your application.
Importing Ionic Modules
As you will see from using an Ionic application, we heavily rely on the use of modules. In fact, just about every single .ts
file in your application will import modules from elsewhere in the application, and export its own. Let’s take a look at a basic page that Ionic will generate for us:
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
constructor(public navCtrl: NavController) {
}
}
We are importing two modules here: Component and NavController. By importing Component from the Angular core library, we are able to use that functionality to add the @Component
decorator to our HomePage
class so that Angular knows that this is a component. By importing NavController from the Ionic library, we are able to make use of the NavController service which will allow us to perform navigation operations like pushing a new page, or changing the root page of the application.
I indicated in my original example that you should specify the path to the file that you are importing from. The example above does not do that. If we were to give the actual path to the ionic-angular
library it would look more like this:
'../../../node_modules/ionic-angular'
This uses ../
to traverse through the folder structure of the project to find the file (the ../
means “go up one folder”, whereas ./
means to look in the current folder).
But we don’t need to do that. If we do not start our import paths with /
, ./
, or ../
then a “non-relative” import will be used. TypeScript has its own logic for figuring out where exactly a module should be imported from if it is not given a relative path, but I won’t be going into that here. If you are interested in the process, you should read this.
Just keep this in mind: if you are importing a module that you have created in your project you should supply a relative path, if you are importing a module from some library you have installed you should use a non-relative path.
Now, let’s dive a little deeper and see where that NavController is actually coming from. If we were to go to the actual ionic-angular
library included in the node_modules
folder you would find a file called index.d.ts. Inside of that file, you would find NavController being exported:
export { NavController } from './navigation/nav-controller';
That’s just exporting the functionality from another file where the NavController is actually defined, where you would find the actual code that is being exported:
export declare abstract class NavController {
// functions like push() etc. are defined in here
}
The functionality in this file is what is being imported when we do this:
import { NavController } from 'ionic-angular';
Of course, you don’t need to understand what happens behind the scenes – Ionic provides some functionality and you use it – but I think it does help to have context and understand how things actually work behind the scenes.
Importing Third-Party Modules
We can, of course, import things from the Ionic library and the Angular library which live in the node_modules
folder, but we can also install other libraries there, and we can also import modules from those libraries.
It may not be the same for all libraries, but generally speaking, you could do the following:
1. Install the library
npm install THE_LIBRARY
2. Install the types for the library (if available)
npm install @types/LIBRARY_NAME
3. Import modules into your application
import SomeModule from 'library_name';
I have created a video example of installing a 3rd party library if you would like to check that out.
Creating and Importing Your Own Modules
You are not limited to just exporting pages and providers as modules. You can export, and import elsewhere, any class, function, or even just a variable.
As I eluded to in my basic example at the start, you just have to define some class or function, export it, and then import it using the file path somewhere else. You may not often have to do this, but it can be useful for doing things like providing utility functions.
In another tutorial, I decided to create my own class that would determine what providers should be used in my application (based on whether the application was running through the browser or on a device). The class was defined and exported as follows:
app.providers.ts
export class AppProviders {
public static getProviders() {
// .. snip
}
}
and then I imported this into the app.module.ts file and used the AppProviders
class that I was exporting:
import { NgModule } from '@angular/core';
import { IonicApp, IonicModule } from 'ionic-angular';
import { MyApp } from './app.component';
import { AppProviders } from './app.providers';
import { HomePage } from '../pages/home/home';
@NgModule({
declarations: [MyApp, HomePage],
imports: [IonicModule.forRoot(MyApp)],
bootstrap: [IonicApp],
entryComponents: [MyApp, HomePage],
providers: AppProviders.getProviders(),
})
export class AppModule {}
Notice that I use the ./
relative path, because the module is being imported from the same folder that it is being exported in.
Summary
Using modules in Ionic is simple enough that you don’t really need to understand how they work to use them, but I think understanding how to use them is useful. It stops the feelings of “how does this magic work?” and it also makes you better able to make use of modules in situations where you otherwise wouldn’t have considered using them (like in my AppProviders
example above).