Ionic Cookbox

Storage

Routing and Navigation

Basic Angular Router configuration

Create a routing module that is ‘visible’ to all components in your app

With Angular CLI

ng generate module app-routing

With Ionic

ionic start my-app blank --type=angular

Match URL paths to Pages/Components

// add to app-routing.module.ts
const routes: Routes = [
    { path: 'home', 
      loadChildren: './home/home.module#HomePageModule'
    },
    { path: 'list',
      loadChildren: './list/list.module#ListPageModule'
    },
    { path: 'about', 
      loadChildren: './about/about.module#AboutPageModule'
    }
]

Update routing module imports and exports

app.modules.ts

imports { RouterModule, Routes } from '@angular/routes';
imports: [
    RouterModule.forRooot(routes)
    # forRoot makes module available 'application wide'
]   
exports:[          
    RouterModule
]

Do not forget to import the routing module to you main app module

app.routing.module

import { AppRoutingModule } from './app-routing.module';
imports:[
    AppRoutingModule
]

Add a router-outlet to indicate where the pages will be rendered

app.component.html

<ion-app>
    <ion-router-outlet></ion-router-outlet>
</ion-app>

Basics

src/app/app-routing.module.ts

const routes: Routes = [
   { path: 'hello', component: HelloPage }
];

app.component.html

<ion-app>
  <ion-router-outlet></ion-router-outlet> 
</ion-app>
  // Regular Route
  { path: 'eager', component: MyComponent },

  // Lazy Loaded Route (Page)
  { path: 'lazy', loadChildren: './lazy/lazy.module#LazyPageModule' },

    // Redirect
  { path: 'here', redirectTo: 'there', pathMatch: 'full' }
];
<ion-button href="/hello">Hello</ion-button>
<a routerLink="/hello">Hello</a>

Navigate Programmatically

import { Component } from '@angular/core';
import { Router } from '@angular/router';

@Component({ ... })
export class HomePage {
  constructor(private router: Router) {}

  go() {
    this.router.navigateByUrl('/animals');
  }
}

Navigate to Dynamic URLS

const routes: Routes = [
  // Regular Route
  { path: 'items/:id', component: MyComponent },
];
<ion-button href="/items/abc">ABC</ion-button>
<ion-button href="/items/xyz">XYZ</ion-button>

Extract Data from Routes with ActivatedRoute

When working with dynamic data, you need to extract the params from the URL.

For example, you might want to read from the database when the user navigates to /items/:id, using the ID from the route to make a query.

Angular has an ActivatedRoute service that allows us to grab information from the current route as a plain object or Observable.

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({ ... })
export class ProfileComponent implements OnInit {

  id: string;

  constructor(private route: ActivatedRoute) {}

  ngOnInit() {
    this.id = this.route.snapshot.paramMap.get('id');
  }
}

Or if we need to react to changes, we can subscribe to an Observable.

ngOnInit() {
  this.route.params.subscribe(...);
}

Routing in Tabs

{
  path: 'contact',
  outlet: 'modal',
  component: ContactModal
}
http://.../(modal:contact)

Lazy Loading

app-routing.module.ts

const routes: Routes = [
  { path: 'about', loadChildren: './about/about.module#AboutPageModule' },
];

about/about.module.ts

const routes: Routes = [
  { path: '', component: AboutPage },
];

Using Guards

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {
  constructor(private router: Router) {}

  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): boolean {

    const loggedIn = false; // replace with actual user auth checking logic

    if (!loggedIn) {
      this.router.navigate(['/']);
    }

    return loggedIn;
  }
}
const routes: Routes = [
  { path: 'special', component: SpecialPage, canActivate: [AuthGuard] },
];

Components

Directives

Pipes

HTML Elements

Access HTML Element from Page Class

<div #box></div>
@ViewChild('box') el_box:ElementRef;
box: any;

constructor() {
this.box = this.el_box.nativeElement;

Grabbing Ionic Components with ViewChild

Let’s imagine we have a HomePage component that looks like this and we want to close the menu when an item is clicked.

<ion-menu>
  <!-- with some stuff inside -->
</ion-menu>

Our goal is to access the ion-menu from the TypeScript code so we can call its API methods, like open() and close().

import { Component, ViewChild } from ‚@angular/core‘;
import { Menu } from ‚@ionic/angular‘;

@Component(…)
export class HomePage {

@ViewChild(Menu) menu: Menu;


onDrag() {
this.menu.close();
}
}

Shortcut: Use Template Variables

There’s actually a very convenient shortcut to using ViewChild in a component. We never have to leave the HTML by setting a template variable in Angular. In this example we reference the menu component with a hashtag and variable name #mymenu.

<ion-menu #mymenu>
<!– with some stuff inside –>

<ion-item (click)=“mymenu.close()“></ion-item>
</ion-menu>

And we’re done. Much easier then using ViewChild in the TypeScript.

Grabbing Multiple Components with ViewChildren

You might also run into a situation where there are multiple components of the same type on the page, such as multiple FABs:

<ion-fab></ion-fab>
<ion-fab></ion-fab>
<ion-fab></ion-fab>

ViewChildren is almost the same, but it will grab all elements that match this component and return them as an Array.

import { Component, ViewChildren } from ‚@angular/core‘;
import { Fab } from ‚@ionic/angular‘;

@Component(…)
export class HomePage {

@ViewChildren(Fab) fabs: Fab[];


closeFirst() {
this.fabs[0].close();
}
}

Now that you know about ViewChild, you should have no problem accessing the API methods found on Ionic’s web components.

Loops in HTML Elements

<ul>
   <li *ngFor="let number of [0,1,2,3,4]">
      {{number}}
   </li>
</ul>
<ul>
  <li *ngFor='#key of [1,2]'>
    {{key}}
  </li>
</ul>
<ul>
  <li *ngFor='#val of "0123".split("")'>{{val}}</li>
</ul>
<ul>
  <li *ngFor='#val of counter(5) ;#i= index'>{{i}}</li>
</ul>

export class AppComponent {
  demoNumber = 5 ;

  counter = Array;

  numberReturn(length){
    return new Array(length);
  }
}

Display Array

<ion-grid class="board">
  <ion-row *ngFor="let r of [0,1,2]">
    <ion-col col-4 class="cell" *ngFor="let c of [0,1,2]" (click)="handle(c+r*3)">
            {{squares[c+r*3]}}
    </ion-col>
  </ion-row>
</ion-grid>

Change CSS class on click

Add handler to html element

<a class="btn" (click)='toggleClass($event)'>
    <ion-icon class="icon" name="bluetooth"></ion-icon>
</a>

Import Render2 in page.ts

import { Component, OnInit, Renderer2 } from '@angular/core';
...

constructor(private renderer: Renderer2) { }

Write handler to toggle class

toggleClass(event: any) {
    const classname = 'active';

    if (event.target.classList.contains(classname)) {
        this.renderer.removeClass(event.target, classname);
    } else {
        this.renderer.addClass(event.target, classname);
    }
}