Search code examples
androidangularnativescriptangular2-routingnativescript-angular

Navigating nested routes in NativeScript Angular


In my NativeScript Angular Project this is my router module:

export const routes = [
 {path: "user", component: UserComponent,
    children: [
        {
            path: "dashboard",
            component: DashboardComponent
        },
        {
            path: "notice",
            component: NoticeComponent
        },
        {
            path: "attendance",
            component: AttendanceComponent
        },
        {
            path: "subject",
            component: SubjectComponent,
            children: [
                {
                    path: "discussion",
                    component: DiscussionComponent
                },
                {
                    path: "assignment",
                    component: AssignmentComponent,
                    children: [
                        {
                            path: "assignment-report", component: AssignmentReportComponent
                        }
                    ]
                }
            ]
        }
    ]
  }
];

The user.component.html has a bottom bar with links for Dashboard, Notice and Attendance components which are displayed in a router outlet in UserComponent. A user clicks on a subject in user/dashboard route to go to a subject. The SubjectComponent again has two tabs for 'Discussion' and 'Assignment' displayed in a router outlet inside SubjectComponent.

Problem: When I am in SubjectComponent and click on any of the links in the bottom bar to navigate to Dashboard, Attendance or Notice, the app crashes and I get this error:

An uncaught Exception occurred on "main" thread. Calling js method onPause failed Error: java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on a null object reference .

It works fine if I just remove the <page-router-outlet> in SubjectComponent. I know I am somewhere messing up in nesting these routes but the error doesn't throw anything specific so I am unable to figure out.

Playground Sample: Open the playground sample and click on "Open Subject" button. When you are on the Subject Page, click on "Dashboard" button at the bottom. You will get the error. Playground Link: https://play.nativescript.org/?template=play-ng&id=qGvsVF&v=11

Adding some code snippets that might be relevant to this problem.

user.component.html

<GridLayout style="background-color: #ffffff;" rows="*, auto">
<StackLayout class="content-container" row="0">
    <page-router-outlet></page-router-outlet>
</StackLayout>
<StackLayout class="bottom-bar" row="1">
    <StackLayout class="menu-container" horizontalAlignment="center" orientation="horizontal">
        <Image (tap)="openDashboard()" [ngStyle]="{'border-color': isHome?'#1d87c9' :'#ffffff'}" class="btn-home" [src]="menuImages[0]"></Image>
        <Image (tap)="openNotice()"  [ngClass]="{'btn-active': isNotice}" class="btn-icon" [src]="menuImages[1]"></Image>
        <Image (tap)="openAttendance()" [ngClass]="{'btn-active': isAttendance}" class="btn-icon" [src]="menuImages[2]"></Image>
    </StackLayout>
</StackLayout>

openDashboard() method in user.component.ts. openNotice() and openAttendance() are similar

import { RouterExtensions } from "nativescript-angular/router";

constructor(private routerExtensions: RouterExtensions) {}

openDashboard(){
  this.routerExtensions.navigateByUrl('user/dashboard');
  this.menuImages = ["res://uni_full","res://notice_default","res://attendance_default"];
  this.isHome = true;
  this.isNotice = false;
  this.isAttendance = false;
}

subject.component.html

<StackLayout class="main">
<GridLayout rows="auto, *">
    <StackLayout row="0" class="subject-ribbon">
        <StackLayout class="tab-container" orientation="horizontal">
            <StackLayout (tap)="changeTab('discussion')" class="tab">
                <Label class="tab-label" text="&#xf27a;&nbsp;&nbsp;&nbsp;Discussion"></Label>
                <Label class="tab-indicator"></Label>
            </StackLayout>
            <StackLayout (tap)="changeTab('assignment')" class="tab">
                <Label class="tab-label" text="&#xf15c;&nbsp;&nbsp;&nbsp;Assignment"></Label>
                <Label class="tab-indicator"></Label>
            </StackLayout>
        </StackLayout>
    </StackLayout>
    <ScrollView (scroll)="onScroll($event)" row="1">
        <StackLayout>
            <page-router-outlet></page-router-outlet>
        </StackLayout>
    </ScrollView>
</GridLayout>

subject.component.ts

import { RouterExtensions } from "nativescript-angular/router";
constructor(private routerExtensions: RouterExtensions) {}

changeTab(tabName){
  this.tabMode = tabName;
  this.routerExtensions.navigateByUrl('user/subject/' + tabName);
}

Solution

  • I suspect the issue is that you had wrapped your frame (page-router-outlet) with a ScrollView. It's not a good practice for various reasons and the app seems to crash because of that. Moving the ScrollView within the page resolves the issue.

    Updated Playground