Nativescript-angular: Question; how to detect routerExtensions.back(); in the target Page?

Created on 4 Jan 2017  路  11Comments  路  Source: NativeScript/nativescript-angular

Is there a way to detect routerExtensions.back(); in the target page ?

I tried some of the component lifecycle hooks (constructor, ngOnInit, ngAfterContentInit, ngAfterViewInit, ....) but none is being called.

Thanks

question

Most helpful comment

Look at my new post below for the updated solution.

Original post:

For those who want to specifically detect back navigation to a page can use this in target page component file:

Import
ts import { PlatformLocation } from '@angular/common';

Get service:
ts constructor(private location : PlatformLocation){}

Use it:
ts ngOnInit() : void { this.location.onPopState(() => { // Do whatever you want }); }

All 11 comments

Hi @devna13,
For your case you could listen for Angular 2 router event and to check for NavigationEnd event. TO be able to handle just the event for the specific page you could also check for the current url, you are navigating to. You could review the below-given example for this case.

import { Component, ChangeDetectionStrategy } from "@angular/core";
import { Link } from "./../link";
import {Router, Event, NavigationEnd} from '@angular/router';
.....
@Component({
    moduleId: module.id,
    templateUrl: "./../examples-list.component.html",
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class ApplicationExamplesComponent {
    public links: Array<Link>;

    constructor( private router:Router ) {
        .........
        this.router.events.subscribe((val) => {
            if(val instanceof NavigationEnd){
                if(this.router.url == "/application"){
                    console.log("navigation end");
                };
            } 
        });
    }
}

Another option is to register for page navigatingToEvent, which will be fired, when you are navigating to the target Page. I am attaching sample code.

import { Component, ChangeDetectionStrategy } from "@angular/core";
import { Link } from "./../link";
import {Page} from "ui/page";


@Component({
    moduleId: module.id,
    templateUrl: "./../examples-list.component.html",
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class ApplicationExamplesComponent {
    public links: Array<Link>;

    constructor(private page:Page) {
      ........
        this.page.on(Page.navigatingToEvent, function(){
            console.log("navigating to this page");
        })

}

Hope this helps.

Perfect answer! @tsonevn :1st_place_medal:

Look at my new post below for the updated solution.

Original post:

For those who want to specifically detect back navigation to a page can use this in target page component file:

Import
ts import { PlatformLocation } from '@angular/common';

Get service:
ts constructor(private location : PlatformLocation){}

Use it:
ts ngOnInit() : void { this.location.onPopState(() => { // Do whatever you want }); }

changeDetection doesn't work for me, my page is empty using that

Hi @jdnichollsc ,
Could you provide some more info about the problem? It would help if you could provide sample project, which could be used for debugging.

@erkanarslan What about unregister it ? What is the right way to unsubscribe it ? ( and how)

@erkanarslan, @RoyiNamir I'm also curious about that. But this isn't Observable/Promise object so I'm not sure if we should or have to unsubscribe that event.

@tsonevn @RoyiNamir @divisble if you unsubscribe then how will it detect router events when coming back from other component?

I have tons of routes if I subscribe to them all and don't unsubscribe doesn't seem right.

Update:

This is how I am unsubscribing:

  subscription: Subscription;

  constructor(private route: ActivatedRoute, private router: Router, private routerExtensions: RouterExtensions) {
    this.subscription = this.router.events.subscribe((val) => {
      this.isLoading = true;
      if (val instanceof NavigationEnd) {
        if (this.router.url == "/dates") {
          console.log("navigation end");
          this.isLoading = false;
          this.subscription.unsubscribe();
        }
      }
    });
  }

IMHO this is somewhat of a limitation, particularly when we need to refresh data on a previous view on the stack.

The ideal behaviour would be somewhat identical to what iOS's UIViewController provides: viewWillAppear:, viewDidAppear:, viewWillDisappear: and viewDidDisappear:, in which case users could hook their refresh routines without needing to do subscription management on the Page object - since you should do page.off(...) after a page.on(...) to avoid leaks.

I'm currently trying to implement these hooks using a service that subscribes to router events, and uses the component instance reference attached to the ActivatedRouteSnapshot that comes with the events (ActivationStart, ActivationEnd)

@RoyiNamir @divisble To unsubscribe from this event, you can use Location service instead of PlatformLocation. Otherwise the implementation I shared above will call the callback function for all navigations back to any page. It is not limited to the page which uses PlatformLocation service.

Import library:

import { Location } from '@angular/common';

Inject it:

constructor(
    private location : Location
) {}

Subscribe to it:

this.locationSub = this.location.subscribe(() => {
    // do whatever you want here
});

Unsubscribe when page destroyed:

ngOnDestroy() : void {
    this.locationSub.unsubscribe();
}

One thing to be careful is that when you navigate from page A to B, page A is not destroyed. It is pushed to navigation history. Because of that if you navigate like A -> B -> A -> C -> A and you subscribe to location on page A, you will have 3 different subscriptions each updating their own copy of the page component. If you are just updating the values in the component, this won't create a problem but if you are sending an http request, or calling a service it will be called 3 times.

You can try to unsubscribe when navigated away from page A but in this case if you navigate back to page A, it won't do the operations that you do in subscribe method.

Using

ngOnInit() : void {
    this.location.onPopState(() => {
        // Do whatever you want
    });
}

produces undesirable behavior as it is triggered on every pop. I found the following more suitable for this.

import { Page } from 'tns-core-modules/ui/page/page';

export class MyComponent implements OnInit {
    constructor(private page: Page) {}
    ngOnInit() {
    this.page.on('navigatedTo', (data) => {
      if (data.isBackNavigation) {
       // do stuff
      }
    });
  }
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

sis0k0 picture sis0k0  路  3Comments

triniwiz picture triniwiz  路  3Comments

sarvagayatri picture sarvagayatri  路  3Comments

sunpasup picture sunpasup  路  3Comments

tsonevn picture tsonevn  路  3Comments