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
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
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);
}
}
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).
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.
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
.
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.
RouteMap
codeThis 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
.
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:
/tabbedpage
/tabbedpage
to /tabbedpage/tab1
foundTabbedPage
is created and bound to /tabbedpage/tab1
/tabbedpage
to /tabbedpage/tab1
Tab1
is createdAfter 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
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
I did this one and it works for me:
ionViewWillEnter() {
console.log(this.router['routerState'].snapshot.url);
}
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
}
}
}
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!