Description
If your main route is guarded by a guard that runs async (e.g. does an Http call before completing the observable), the Page.navigatedToEvent is never called. Linked to that, the action bar shows some weird behavior in that the page title is not removed if it's overridden in the template.
In the example below, change .timer(300)
to .of(true)
, and it will work as expected.
This only appears to happen in the initial navigation. Subsequent navigations appear to work as expected.
Route guard:
import {CanActivate} from "@angular/router";
import {Observable} from "rxjs";
export class Guard implements CanActivate {
canActivate() {
return Observable.timer(300).mapTo(true);
}
}
AppModule:
import { NgModule, APP_INITIALIZER, NO_ERRORS_SCHEMA } from "@angular/core";
import { NativeScriptModule } from "nativescript-angular/nativescript.module";
import { AppComponent } from "./app.component";
import {NativeScriptRouterModule} from "nativescript-angular";
import {HomeComponent} from "./home.component";
import {Observable} from "rxjs";
import {Guard} from "./guard.service";
var pages = [
{ path: "", component: HomeComponent, canActivate: [Guard] }
]
@NgModule({
bootstrap: [AppComponent],
declarations: [AppComponent, HomeComponent],
imports: [NativeScriptModule, NativeScriptRouterModule, NativeScriptRouterModule.forRoot(pages)],
schemas: [NO_ERRORS_SCHEMA],
providers: [Guard]
})
export class AppModule {}
AppComponent:
import {Component} from "@angular/core";
@Component({
selector: "my-app",
template: `
<page-router-outlet></page-router-outlet>
`
})
export class AppComponent {
}
HomeComponent:
import {Component, OnInit} from "@angular/core";
import {Page} from "tns-core-modules/ui/page/page";
@Component({
template: `
<ActionBar title="My App" class="action-bar">
<Label text="test"></Label>
</ActionBar>
<Label text="test"></Label>
`,
})
export class HomeComponent implements OnInit {
constructor(private page: Page) {
}
ngOnInit() {
this.page.on(Page.navigatedToEvent, () => console.log('navto'))
}
}
I tried to circumvent it by setting initialNavigation
to false in the router, loading all the necessary data for the Guard in an APP_INITIALIZER and triggering initialNavigation
from there, but that seems to yield the same behavior. In that case, this is the code:
AppModule:
import {NgModule, APP_INITIALIZER, NO_ERRORS_SCHEMA, Injector} from "@angular/core";
import { NativeScriptModule } from "nativescript-angular/nativescript.module";
import { AppComponent } from "./app.component";
import {NativeScriptRouterModule} from "nativescript-angular";
import {HomeComponent} from "./home.component";
import {Observable} from "rxjs";
import {Guard} from "./guard.service";
import {Router} from "@angular/router";
var pages = [
{ path: "", component: HomeComponent, canActivate: [Guard] }
]
@NgModule({
bootstrap: [AppComponent],
declarations: [AppComponent, HomeComponent],
imports: [NativeScriptModule, NativeScriptRouterModule, NativeScriptRouterModule.forRoot(pages, {initialNavigation:false})],
schemas: [NO_ERRORS_SCHEMA],
providers: [Guard, {
provide: APP_INITIALIZER,
useFactory: (injector: Injector) => () => {
Observable.timer(300).do(() => {
injector.get(Router).initialNavigation();
}).toPromise();
},
deps: [Injector],
multi: true
}]
})
export class AppModule {}
Guard:
import {CanActivate} from "@angular/router";
import {Observable} from "rxjs";
export class Guard implements CanActivate {
canActivate() {
return Observable.of(true);
}
}
This screenshot shows how the text "test"doesn't replace the app title, but is appended to it.