Fixing navigation with Angular routing and hookNavigators

Following-up from my previous-post, I was able to set up nested navigation nodes on my navigator as follows:

import { Injectable } from "@angular/core";
import { NavigatorNode, NavigatorNodeFactory } from "@c8y/ngx-components";

@Injectable()
export class CaseManagementFactory implements NavigatorNodeFactory {
    get(): NavigatorNode {
        const caseManagementNode = new NavigatorNode({
            label: 'Dashboard',
            icon: 'dashboard',
            path: 'case-management',
            priority: 30
        })

        const openCasesNode = new NavigatorNode({
            label: 'Open Cases',
            icon: 'table',
            path: 'case-management/open-cases',
            priority: 20
        });

        caseManagementNode.add(openCasesNode);
        
        return caseManagementNode;   
    }
}

I then import the factory into my component’s module as follows:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { hookNavigator } from '@c8y/ngx-components';

import { CaseManagementComponent } from './case-management.component';
import { CaseManagementFactory } from './case-management.factory';
import { OpenCasesComponent } from './open-cases/open-cases.component';
import { ActiveCasesComponent } from './active-cases/active-cases.component';

@NgModule({
  declarations: [CaseManagementComponent, OpenCasesComponent, ActiveCasesComponent],
  imports: [
    CommonModule
  ],
  exports: [CaseManagementComponent],
  providers: [hookNavigator(CaseManagementFactory)]
})
export class CaseManagementModule { }

Result
image

The difficulty I am facing now is trying to get the child component, open-cases, to appear in the main application space. This component should have the same default message as its parent component .

image

image

Because I intend to add a header to my application, I have also created a routing module for the parent component (and module) case-management, and I wonder if there is a conflict between the routing module and the navigator node factory both sharing the path fields.

CaseManagementRoutingModule

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { CaseManagementComponent } from './case-management.component';
import { OpenCasesComponent } from './open-cases/open-cases.component';

const routes : Routes = [
    {
        path: '',
        component: CaseManagementComponent,
        children: [
            { path: 'open-cases', component: OpenCasesComponent}
        ]
    }
]

@NgModule({
    imports: [RouterModule.forChild(routes)],
    exports: [RouterModule]
})
export class CaseManagementRoutingModule {}

AppRoutingModule

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  {
    path: 'case-management',
    loadChildren: () => import('./features/case-management/case-management-routing.module').then(m => m.CaseManagementRoutingModule)
  },
  { 
    path: '',
    redirectTo: 'case-management', 
    pathMatch: 'full'
  }
];

@NgModule({
  imports: [RouterModule.forRoot(routes, { enableTracing: false, useHash: true })],
  exports: [RouterModule]
})
export class AppRoutingModule { }

After some further investigation, I determined that the problem has nothing to do the NavigationNodeFactory but with how I am setting up the routing in my project.

Currently, I have imported the CaseManagementRoutingModule both to the AppRoutingModule and the AppModule…

Then, I looked back at the tutorial and noticed that the AppModule imports the RouterModule and provides with the Routes object itself.

I am confused as to why we I needed a AppRoutingModule in the first place when I added the Web SDK to our application…

I have since removed the AppRoutingModule from my project and it is working as it should be except for the error I reported at the start.

image

Hi Lucas,

regarding your CaseManagementFactory, I would suggest to restructure it to:

import { Injectable } from '@angular/core';
import { NavigatorNode, NavigatorNodeFactory } from '@c8y/ngx-components';

@Injectable()
export class CaseManagementFactory implements NavigatorNodeFactory {
  rootNode: NavigatorNode;

  constructor() {
    this.rootNode = new NavigatorNode({
      label: 'Dashboard',
      icon: 'dashboard',
      path: 'case-management',
      priority: 30
    });

    const openCasesNode = new NavigatorNode({
      label: 'Open Cases',
      icon: 'table',
      path: 'case-management/open-cases',
      priority: 20
    });

    this.rootNode.add(openCasesNode);
  }

  get(): NavigatorNode {
    return this.rootNode;
  }
}

This way you would not recreate a new NavigatorNode with every call of get() as get is called after every navigation.

I did not really get the what exactly your problem is.
You’ve mentioned:

And from the screenshot it looks like it is having exactly the same default message. Or did you expect a message like open-cases works! instead of case-management works!?

Since routing is not really any different within Cumulocitys Web SDK compared to a plain angular app, maybe you can just provide a stackblitz sample of your setup in a plain angular application?

You could also set enableTracing to true in your RouterModule.forRoot() call to get some debug information regarding routing logged on your console.

Regards,
Tristan

Hi @luclib,

I’ve created a sample that should be working as you would expect it:

When opening the sample, note that you would need to click the link behind Dev server running in the terminal once.

Feel free to use Angular Cumulocity Web SDK Starter - StackBlitz as a template for further questions related to the Web SDK.

Regards,
Tristan

Thank you, Tristan. I will apply your suggestions and get back to you on the result :slight_smile:

Hi @Tristan_Bastian

To clarify my first question: yes, when I click on the navigator node for open-cases it should display open-cases works! on the screen.

Using enableTracing: true enabled me to get to the root of the problem: I had to switch all of my components to standalone:true, else they would not work with the lazy loading technique.

Vielen Danke!