how we can get the current page from app.component

2020-08-26 04:06发布

问题:

i am trying to get current page instance in app.component in ionic 4.

in ionic 3 i can do it like this

this.nav.getActive().instance

回答1:

You can access the url from the Router.

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

export class YourPage implements OnInit {
   constructor(private router: Router) {}

   ngOnInit() {
        console.log('this.router.url', this.router.url);
    }
}


回答2:

I'm in a similar situation. In a multi-page application, I need the instance of the current class component.

Basically, I have a modal that can open on each page and ask the user if she wants to reload data or not. When the user chooses yes, I want to reach the current page instance and call a reload method on it.

I ended up with this dirty trick. I'm not an Angular/JS/Ionic expert, so probably there are better and cleaner ways to do this. Use this at your own risk, in my situation it seems to work, although not perfectly (see later).

The idea

My idea is simple: when a new page component class is instantiated (constructor called), I bind it to the url used to navigate to it .

Class instantiation happens before navigation ends, so when navigation end event occurs, I use the final url to get back the instance.

Code

Invoking code from current page

In my app.component.ts, I put the event handler with the call to the page component methods:

export class AppComponent implements OnInit {
  private navEnd: Observable<NavigationEnd>;

  constructor(
    // ... other dependencies
    private router: Router,
    private routeMap: RouteMap // this is my class, see later
  ) {

    this.navEnd = router.events.pipe(
      filter(event => event instanceof NavigationEnd)
    ) as Observable<NavigationEnd>;
  }

  ngOnInit() {
    this.navEnd.subscribe(evt => {
      let instance = this.routeMap.getObject(evt.urlAfterRedirects);
      if (instance != null) {
        instance.doStuff();
        // ... or save instance elsewhere, like
        //   this.aService.setCurrentPage(instance);
        // or anything you need
      }
    });
  }
}

In the subscribe call, I use evt.urlAfterRedirects instead of evt.url to handle the case when the empty path redirects to the first page, like this (in app-routing.module.ts):

const routes: Routes = [
  { path: '', redirectTo: 'categories', pathMatch: 'full' },
  { path: 'home', loadChildren: './pages/home/home.module#HomePageModule' },
  { path: 'page1', loadChildren: './pages/page1/page1.module#Page1PageModule' },
  // ...
];

If you have a similar configuration, when you navigate / and the NavigationEnd event occurs, evt.url is / and evt.urlAfterRedirects is /home.

When you navigate to /page1 and then go back to home page using the back button, when NavigationEnd occurs, both evt.url and evt.urlAfterRedirects are /home.

To be sure that in both cases I get the instance, I need to user urlAfterRedirects.

Tracking current page

In my pages, I change the constructors like this:

export HomePageComponent implements OnInit {
  constructor(
    private router: Router,
    private routeMap: RouteMap // again my code
  ) {
    routeMap.registerObject(router.getCurrentNavigation().finalUrl.toString(), this);
  }

  // ...
}

Basically, when the constructor is called, I know the instance of the component class, so I bind it to the current url.

This code is quite rough, probably it's better to factorize it out, making a superclass, a decorator, a mixin, so that you don't have to duplicate the code on each page. Being not a Javascript or Angular expert, here I'm a bit lost. I would go with a superclass (because I just know them), but probably it's better something else.

The RouteMap code

This is where tracking happens. It is a little service you can put where you like.

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class RouteMap {
  private map: {
    path: string,
    object: object
  }[] = [];

  getObject(path: string) {
    let item = this.map.find(function (item) {
      return item.path == path;
    });

    return item ? item.object : null;
  }

  registerObject(path: string, object: object) {
    let item = this.map.find(function (item) {
      return item.path == path;
    });

    if (item) {
      item.object = object;
    } else {
      this.map.push({
        path: path,
        object: object
      });
    }
  }
}

The registerObject() first check if the given path has already been mapped to an object. If that is the case, it just update the object, so that you don't have duplicated paths. Otherwise, it adds a new entry in the map.

The getObject() searches the map for the give path and gives the registered object if the path exists. Otherwise it gives null.

Issues

Bad behavior with first tab in tabbed view

In my case, I have a sequence of pages Home -> Page1 -> ... -> PageN -> TabbedPage where the last is a page that has 3 tabs.

TabbedPage has this routing definition:

const routes: Routes = [
  {
    path: '',
    component: TabbedPage,
    children: [
      {
        path: '',
        redirectTo: 'tab1',
        pathMatch: 'full'
      },
      {
        path: 'tab1',
        children: [{
          path: '',
          loadChildren: './tab1/tab1.module#Tab1Module'
        }]
      },
      {
        path: 'tab2',
        children: [{
          path: '',
          loadChildren: './tab2/tab2.module#Tab2Module'
        }]
      },
      {
        path: 'tab3',
        children: [{
          path: '',
          loadChildren: './tab3/tab3.module#Tab3Module'
        }]
      },
    ]
  },
];

so when I navigate to /tabbedpage, it automatically opens the /tabbedpage/tab1 tab.

However, I noticed that if I try to track the Tab1 instance with

export class Tab1 implements OnInit {

  constructor(
    private router: Router,
    private routeMap: RouteMap
  ) {
    routeMap.registerObject(router.getCurrentNavigation().finalUrl.toString(), this);
  }

}

it does not work: getCurrentNavigation() gives null. I logged the navigation events and I've noticed that no navigation occurs from TabbedPage to Tab1. Tab1 is just instantiated.

So I have this sequence of events:

  • navigation starts to /tabbedpage
  • (internal) redirect from /tabbedpage to /tabbedpage/tab1 found
  • TabbedPage is created and bound to /tabbedpage/tab1
  • navigation ends from /tabbedpage to /tabbedpage/tab1
  • Tab1 is created

After that, if I navigate the other tabs, the instances of Tab2 and Tab3 are correctly bound to /tabbedpage/tab2 and /tabbedpage/tab3. If I navigate back to Tab1, I get the instance of TabbedPage.


At the moment I have not found other particular issues, but the code is enough for my case.

Let see if it is useful to you too.

Bye



回答3:

u can track the current page using the routeroutlet

<router-outlet (activate)="componentName = $event"></router-outlet>

check documentation for more info https://angular.io/api/router/RouterOutlet



回答4:

I did this one and it works for me:

ionViewWillEnter() {  
   console.log(this.router['routerState'].snapshot.url);
}


回答5:

in my case I used an observable to solve this situation

here's my url Service

@Injectable({
  providedIn: 'root'
})
export class CurrentPageService {
  private $urlParts:BehaviorSubject<any>;
  private url;
  constructor(private router:Router) { 
    this.$urlParts = new BehaviorSubject(null);
  }
  get urlParts(){
    return this.$urlParts.asObservable();
  }
  setUrl(){
    this.url=this.router.url;
    let parts = this.url.split('/');
    return this.$urlParts.next(parts);
  }
}

and any page that I'm interested in getting its currently active state in my app component i trigger this observable

export class HomePage {
  constructor(private currentPage:CurrentPageService) {

  }
ionViewDidEnter(){
  this.currentPage.setUrl();
}

and finally in my appcomponent

export class AppComponent {
urlParts;
constructor(private currentpage:CurrentPageService){
      this.currentPage.urlParts.subscribe(url=>this.urlParts=url);
    });
}
foo(){
        if (!this.urlParts.includes('home')) {
          //do something
        }
}

}


回答6:

In Ionic 4 use below code to get current page name using NavController

import { NavController } from '@ionic/angular';

constructor(public navCtrl: NavController) {

}

ngOnInit() {
    console.log(this.navCtrl.router.routerState.snapshot.url)
}

Hope this will helps!