Search code examples
angularionic-frameworknavionic2viewchild

How to navigate into an Ionic 2 app


I'm trying to do a small app in Ionic 2 but I can't manage to navigate... I have read the documentation, navigation stuff, navController, some post on StackOverflow... I tried for hours but I'm stuck ! I had several issues.

I had to find a way to use navController into my app.js, which I did thanks to @viewChild and StackOF. I don't fully understand the principle. I set rootPage: any = Login;. As I have a menu on my app, I disabled it on this page. On a button (click), I set the root this.nav.setRoot() with HomePage. Now from the HomePage, within the menu, I want to navigate through some pages. I'm stuck here. I used the (click)="openPage(Messagerie)" method. First issue, the parameter in openPage() is undefined. Then I tried the [navPush]="pageMessagerie" and this.pageMessagerie = Messagerie; method following the documentation, but it didn't works as well, nothing happen. So, I tried to hard-code the page into my openPage() function : this.nav.push(Messagerie);. Here I have another issue again. The first time I call the push(), the page seems to appear and disappear immediately, coming back on the HomePage. The second time I click, it seems to work. I can go on the Messagerie page and come back on the HomePage via the back button on the navbar.

So... Here I am, stuck with the navigation ! I don't know what to do. Here is my code.


Update Ok the undefined is ok now. But my nav still act weird. When I use this.nav.push() on the home page I got this workflow : Click on Messagerie : Open Messagerie and immediately back on Home Page. Click on Demandes : Open Messagerie, immediately Demandes and stay there. Click on navbar back button : Back to Messagerie, back to Demandes and back to Home Page. Of course if I use this.nav.setRoot() each time it works but I lose the nav principle.


App.html

<ion-menu [content]="content">
    <ion-toolbar>
        <ion-title>Menu</ion-title>
    </ion-toolbar>
    <ion-content>
        <ion-list>
            <button ion-item menuToggle = "left">
                Mes informations
            </button>
            <button ion-item menuToggle = "left" (click)="openPage(Messagerie)">
                Ma messagerie
            </button>
            <button ion-item menuToggle = "left" (click)="openPage(Demandes)">
                Mes demandes
            </button>
        </ion-list>
    </ion-content>
</ion-menu>

<ion-nav id="nav" #content [root]="rootPage"></ion-nav>

App.ts

import {Component, ViewChild}  from '@angular/core';
import {Platform, ionicBootstrap, NavController} from 'ionic-angular';
import {StatusBar}  from 'ionic-native';
import {HomePage}   from './pages/home/home';
import {Messagerie} from './pages/messagerie/messagerie';
import {Demandes}   from './pages/demandes/demandes';
import {Login}      from './pages/login/login';

@Component({
    templateUrl: 'build/app.html' 
})

export class MyApp {

    @ViewChild('content') nav

    rootPage: any = Login;

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

    openPage(page) {
        console.log(page);
        this.nav.push(page);
    }
}

ionicBootstrap(MyApp);

Login.ts (with the setroot)

import {Component}      from '@angular/core';
import {NavController, MenuController}  from 'ionic-angular';
import {FormBuilder, ControlGroup, Validators} from '@angular/common';
import {HomePage}       from '../home/home';

@Component({
    selector: 'mc-login',
    templateUrl: 'build/pages/login/login.html'
})
export class Login {

    loginForm: ControlGroup;

    loginChanged:       boolean = false;
    motdepasseChanged:  boolean = false;
    submitAttempt:      boolean = false;

    constructor(private nav: NavController, private formBuilder: FormBuilder, private menu: MenuController) {
        this.menu.enable(false);
        this.loginForm = formBuilder.group({
            login: ['', Validators.compose([Validators.maxLength(10), Validators.pattern('[a-zA-Z ]*'), Validators.required])],
            motdepasse: ['', Validators.compose([Validators.maxLength(10), Validators.pattern('[a-zA-Z ]*'), Validators.required])]
        });
    }

    elementChanged(input) {
        let field = input.inputControl.name;
        this[field+"Changed"] = true;
    }

    logintoapp() {
        this.submitAttempt = true;

        if(this.loginForm.valid) {
            this.logindatabase();
        } else {
            console.log("Nope");
        }    
    }

    logindatabase() {
        this.nav.setRoot(HomePage);
    }
}

Do I miss something ? What am I doing wrong ? Thanks a lot for your help !


Solution

  • Could you try this:

    In app.ts, declare the nav and following array as following:

    @ViewChild(Nav) nav:Nav;
    
    browsePages:Array<{title:string, component:any}>;
    

    add to your constructor (this is just need to explicitly close the menu later):

    private menu: MenuController
    

    inside your constructor declare your pages you want to add to your menu:

    this.browsePages = [
            {title: 'Ma messagerie', component: Messagerie},
            {title: 'Mes demandes', component: Demandes}
        ];
    

    replace your buttons "Ma messagerie" et "Mes demandes" in html like following:

    <button ion-item *ngFor="let p of browsePages" (click)="openPage(p)">
       {{p.title}}
    </button>
    

    and then finally your openPage method:

    openPage(page) {
        // close the menu when clicking a link from the menu
        this.menu.close();
        // navigate to the new page if it is not the current page
        this.nav.setRoot(page.component);
    }
    

    That was for the navigation from the menu.

    Now about the navigation from the login page...replace your setroot with a navigation push. Generally speaking, except when you really need to set the root you should, I think, push pages in the stack to navigate not set the root again. So basically use push and pop on the navcontroller to navigate.

    *** UPDATE to go to the next page and removing current one from history

    logindatabase() {
        this.goToNextPageWithoutBack(HomePage);
    }
    
    private goToNextPageWithoutBack(page:any, params?:any) {
        this.nav.push(page, params).then(() => {
            this.removeCurrentViewFromHistory();
        });
    }
    
    private removeCurrentViewFromHistory() {
        const index = this.nav.getActive().index;
        this.nav.remove(0, index);
    }
    

    **** UPDATE

    And then to display the menu toggle in your homepage.html add

    <ion-header>
    <ion-navbar>
    
    <button menuToggle start>
      <ion-icon name="ios-menu-outline"></ion-icon>
    </button>
    
    <ion-title>my-items</ion-title>
    </ion-navbar>
    </ion-header> 
    

    I tried to extract these lines from my working codes, hope it gonna help you.