Using NavController from a Provider - is it possible?


#1

I’m trying to create a routing Provider to allow navigation from app-based events, rather than user-based.
I’d like to be able to push a page onto the stack from anywhere in the app using my Provider.
I’ve added my provider to app.component so it will be available app wide to listen for events from anywhere.
When the app starts I get:

Runtime Error
No provider for NavController!

Is it possible to get this working?


#2

Maybe, but I consider it provider abuse. Providers should be for slinging data around, not for view layer interaction, in my opinion.

If you insist on going down this road, I would put the NavController interaction into the app component. It could listen to events from your shadow router.


#3

You can inject App into your provider/service and then use it to get NavController instance.
For example:

import {Injectable} from '@angular/core';
import {App} from "ionic-angular";

@Injectable()
export class MyService {

    constructor(public app: App) {
    }

    someNavigationMethod(): void {
        let nav = this.app.getActiveNav();
        // there is also this.app.getRootNav()

        nav.push(...)
        nav.pop(...)
        nav.setRoot(...)
        // etc
    }
}

Pay attention to the nav structure if you are navigating this way. Maybe it’s not best practice, but i’ve used this for some navigation cases.


#4

You’re probably right.

I was taking over some old code and it was so messy I couldn’t trace the flow from one Component to the next.
I thought that if I centralized navigation it would make things clearer on a large project. (I have a Rails background if you’re familiar with that.)
I also strive to decouple my code and having Components know about each other breaks that a little bit.

It might be more trouble than it’s worth though. Especially because tabs are handled differently.


#5

Thanks for this!
It may not be best practice, but now I know how at least.


#6

you can use EventEmitter for this purpose

this in your provider
navigationEvent = new EventEmitter();

this code to to emit events from your provider

navigate(pageComponent){
   this.navigationEvent.next({page:pageComponent})
}

and this in your app.component.ts controller

this.providerName.navigationEvent.subscribe(
        data => {
            this.nav.push(data.page);
       }
 )

you can pass extra data if you want.
hope this will be of any use to you.


#7

Could you please explain in detail? I want to create an alert in provider and button with handler this.nav.push('CartPage')
how to accomplish that with eventemitter?


#8

Thanks @tanveer, this worked for me in a lazy loading app and i was gettin’ an error due to the injection of App in a service. :smiley: