Reputation: 37
I am using a <page-router-outlet></page-router-outlet>
and <BottomNavigation></BottomNavigation>
setup for tabs in my Nativescript Angular project, and am having trouble navigating from 1 child tab route to another child tab route.
So here is the app-routing.module.ts
:
const routes: Routes = [
{ path: '', redirectTo: '/auth', pathMatch: 'full' },
{ path: 'auth', component: AuthComponent },
{ path: 'individual-tasks', component: SpecificTasksComponent },
{
path: 'tabs',
component: TabsComponent,
children: [
{
path: 'feed',
loadChildren: '~/app/pages/feed/feed.module#FeedModule',
component: NSEmptyOutletComponent,
outlet: 'feedTab'
},
{
path: 'notification',
loadChildren: '~/app/pages/notification/notification.module#NotificationModule',
component: NSEmptyOutletComponent,
outlet: 'notificationTab'
},
{
path: 'create',
loadChildren: '~/app/pages/create/create.module#CreateModule',
component: NSEmptyOutletComponent,
outlet: 'createTab'
},
{
path: 'profile',
loadChildren: '~/app/pages/profile/profile.module#ProfileModule',
component: NSEmptyOutletComponent,
outlet: 'profileTab'
}
]
}
];
And I am currently trying to navigate from within the create tab module to the feed tab module. Here is the create-routing.module.ts
:
const routes: Routes = [
{ path: '', redirectTo: 'create', pathMatch: 'full' },
{ path: 'create', component: CreateComponent },
{ path: 'create-tasks', component: CreateTasksComponent },
{ path: 'create-preview', component: CreatePreviewComponent }
];
So if I am currently within the create-preview
route how can I navigate back to the "tabs/feed" outlet thats in the app-routing.module.ts
?
I have been trying this:
this.router.navigate([
'../tabs', {
outlets: { feedTab: ['feed'] }, relativeTo: this.activatedRoute
}
]);
but even though I am explicitly writing that the navigation should be to the feedTab, it still navigates to the starting outlet (profile) instead of the feed outlet. It is like the outlet stated is entirely ignored... Any ideas???
Upvotes: 0
Views: 1214
Reputation: 1764
One of the comments asked to clarify how to use a BehaviorSubject
for this purpose, so I'll post this code in case it can help someone in the future. This will show how to use a rxjs BehaviorSubject
to listen for tab changes and also provide a way to change the current tab of the BottomNavigation
from anywhere within the app using this service.
The purpose of this service is to provide a central place where the BottomNavigation UI element can be accessed throughout the app. It can:
ElementRef
of BottomNavigation
so the nativeElement
can be accessed to get or change the current tab of the BottomNavigation
element.BehaviorSubject
observable that allows consumers of this service to subscribe to and then be notified of BottomNavigation selectedIndexChanged
events. The newIndex
and oldIndex
are emitted from this rxjs BehaviorSubject
observable on every BottomNavigation selectedIndexChanged
event.NOTE: In the component that has the BottomNavigation
element in its template (app.component.ts in this example), it must give this NavigationService
the reference to the BottomNavigation
it needs in its ngAfterViewInit
life cycle hook like: this._navigationService.bottomNavigationRef = this.navRef;
(see snippet in app.component.ts below)
// navigation.service.ts
import { ElementRef, Injectable, OnDestroy } from '@angular/core';
import { BottomNavigation, SelectedIndexChangedEventData } from '@nativescript/core';
import { BehaviorSubject, Subscription } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class NavigationService implements OnDestroy {
private _bottomNavigationRef: ElementRef<BottomNavigation>;
private _subscription: Subscription;
private callbackSelIndexChgEv;
/** rxjs BehaviorSubject observable to track the current tab of the BottomNavigation */
bottomNavigationTab$: BehaviorSubject<{ newIndex: number; oldIndex: number }>;
constructor() {
// Must initialize rxjs BehaviorSubject observable with initial value.
this.bottomNavigationTab$ = new BehaviorSubject({
newIndex: -1,
oldIndex: -1,
});
// Logs the current tab per this service.
this._subscription = this.bottomNavigationTab$.subscribe((value) => {
console.log(
`NavigationService -> The BottomNavigation current tab index is now:
newIndex: "${value.newIndex}"
oldIndex: "${value.oldIndex}"`
);
});
}
ngOnDestroy(): void {
this._subscription.unsubscribe();
this._bottomNavigationRef.nativeElement.off(
BottomNavigation.selectedIndexChangedEvent,
this.callbackSelIndexChgEv
);
}
get bottomNavigationRef(): ElementRef<BottomNavigation> {
return this._bottomNavigationRef;
}
set bottomNavigationRef(bottomNavRef: ElementRef<BottomNavigation>) {
this._bottomNavigationRef = bottomNavRef;
this.callbackSelIndexChgEv = (
$event: SelectedIndexChangedEventData
): void => {
/* Update the current tab of the rxjs BehaviorSubject Observable */
this.bottomNavigationTab$.next({
newIndex: $event.newIndex,
oldIndex: $event.oldIndex,
});
};
this._bottomNavigationRef.nativeElement.on(
BottomNavigation.selectedIndexChangedEvent,
this.callbackSelIndexChgEv
);
}
}
// app.component.ts (partial file)
// ...
@ViewChild('bottomNav') navRef: ElementRef<BottomNavigation>;
// ...
ngAfterViewInit(): void {
// Gives the NavigationService the reference to the BottomNavigation it needs.
this._navigationService.bottomNavigationRef = this.navRef;
}
// ...
<!-- app.component.html (partial file just to show #bottomNav) -->
<BottomNavigation #bottomNav>
<!-- ... -->
</BottomNavigation>
// another.component.ts
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subscription } from 'rxjs';
import { NavigationService } from './navigation.service';
@Component({
selector: 'app-another-component',
templateUrl: './another.component.html',
styleUrls: ['./another.component.scss']
})
export class AnotherComponent implements OnDestroy, OnInit {
private _subscription: Subscription;
constructor(private _navigationService: NavigationService) {}
ngOnInit(): void {
// Example using BehaviorSubject Observable:
this._subscription = this._navigationService.bottomNavigationTab$.subscribe(
(selectedTab) => {
console.log(`This component knows that the BottomNavigation current tab is now: ${selectedTab.newIndex} and the old tab was: ${selectedTab.oldIndex}`);
if (selectedTab.newIndex === 2) {
// do something ...
}
}
);
}
ngOnDestroy(): void {
// unsubscribe from BehaviorSubject Observable
this._subscription.unsubscribe();
}
// Example changing the BottomNavigation tab from another component:
changeTab(tab: number): void {
this._navigationService.bottomNavigationRef.nativeElement.selectedIndex = tab;
}
}
rxjs BehaviorSubject
documentation: https://www.learnrxjs.io/learn-rxjs/subjects/behaviorsubject
Upvotes: 2
Reputation: 21908
I don't think the router gives you the ability to switch tabs. You will have to update selectedIndex
of BottomNavigation
and then navigate to particular tab you like.
To update selectedIndex
from child component, use a service with a BehaviorSubject
. Listen to the subject from parent component, update the value from child component.
Upvotes: 1
Reputation: 6016
Try this :
You need to remove this.activatedRoute
from navigate()
, which is assigning current route before the routing path which you have provided now.
this.router.navigate(['../tabs/feed', {
outlets: { primary: ['feed'], feedTab: ['feed'] }
}
])
you can read more about outlets here
and follow this blog for more details.
Hope this helps.. :)
Upvotes: 0