Display issues with deeply nested components

I'm facing an issue with displaying the third nested component.

Expected:

Hello App Component

Hello Nest-A Component

Hello Nest-1 Component

Hello Test-Z Component

Actual:

Hello App Component

Hello Nest-A Component

Hello Nest-1 Component

Why is my Test-Z component not showing up?

TLDR; StackBlitz - Code Example

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { RouterModule, Routes } from '@angular/router';
import { AppComponent } from './app.component';
import { NestAModule } from './nest-a/nest-a.module';

const rootRoutes: Routes = [
  { path: '', redirectTo: 'nest-a', pathMatch: 'full' },
  { path: 'nest-a', redirectTo: 'nest-a', pathMatch: 'full' },
];

@NgModule({
  imports: [ 
    BrowserModule, 
    FormsModule,
    RouterModule.forRoot(rootRoutes),
    NestAModule,
  ],
  declarations: [ 
    AppComponent, 
  ],
  bootstrap: [ 
    AppComponent 
  ]
})
export class AppModule { }

app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: '<h1>Hello App Component</h1><router-outlet></router-outlet>',
})
export class AppComponent {
}

nest-a/nest-a-routing-module.ts

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { NestAComponent } from './nest-a.component';
import { Nest1Component } from './nest-1/nest-1.component';

export const nestARoutes = [
  {
    title: 'Nest A',
    path: 'nest-a',
    component: NestAComponent,
    children: [
      { path: '', redirectTo: 'nest-1', pathMatch: 'full' },
      { path: 'nest-1', component: Nest1Component },
    ],
  },
];

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

nest-a/nest-a.component.ts

import { Component } from '@angular/core';

@Component({
    selector: 'my-nest-a',
    template: `<h1>Hello Nest-A Component</h1><router-outlet></router-outlet>`
})
export class NestAComponent {
}

nest-a/nest-a.module.ts

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { NestAComponent } from './nest-a.component';
import { NestARoutingModule, nestARoutes } from './nest-a-routing.module';
import { Nest1Module } from './nest-1/nest-1.module';


@NgModule({
  declarations: [
    NestAComponent,
  ],
  imports: [
    NestARoutingModule,
    Nest1Module,
    RouterModule.forChild(nestARoutes),
  ],
})
export class NestAModule { }

nest-a/nest-1/nest-1-routing.module.ts

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { Nest1Component } from './nest-1.component';
import { TestYComponent } from './test-y/test-y.component'
import { TestZComponent } from './test-z/test-z.component'

export const nest1Routes = [
  {
    title: 'Nest 1',
    path: 'nest-1',
    component: Nest1Component,
    children: [
      { path: '', redirectTo: 'test-z', pathMatch: 'full'},
      { path: 'test-y', component: TestYComponent},
      { path: 'test-z', component: TestZComponent},
    ]
  },
];

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

nest-a/nest-1/nest-1.component.ts

import { Component } from '@angular/core';

@Component({
    selector: 'my-nest-1',
    template: `<h1>Hello Nest-1 Component</h1><router-outlet></router-outlet>`
})

export class Nest1Component {
}

nest-a/nest-1/nest-1.module.ts

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { Nest1Component } from './nest-1.component';
import { Nest1RoutingModule, nest1Routes } from './nest-1-routing.module';
import { TestZModule } from './test-z/test-z.module'

@NgModule({
  declarations: [
    Nest1Component,
  ],
  imports: [
    Nest1RoutingModule,
    TestZModule,
    RouterModule.forChild(nest1Routes),
  ],
})
export class Nest1Module { }

nest-a/nest-1/nest-/nest-.component.ts

(there is an Y and Z, the are no important differences)

import { Component } from '@angular/core';

@Component({
    selector: 'my-test-*',
    template: `<h1>Hello Test-* Component</h1>`
})

export class Test*Component {
}

Answer №1

There are a few issues in your code that are causing problems with router resolution:

  • Your paths are split into different modules, but in the routes definition, you're instructing the router to load a component directly instead of the entire sub-module (which contains the sub-module's route definitions)
  • In your sub-module, the first path should be empty to load the main module component (in nest-1 module, an empty path would load the nest-1 component. It's not the parent module's job to load the sub-module's entry component)
  • You have set up routes in both the router module and the main module (for example, both in the nest-a.module and nest-a.routing.module). Routes should only be defined in one place (the routing module) and then imported into the main module
  • The router is responsible for loading the sub-module using the loadChildren property in the path definition, so there's no need to import the sub-module in your parent module (for example, nest-a.module doesn't need to import nest-1.module)

Below is your modified example following the explanations above. The main changes are:

  • In the parent module's route definition, use the loadChildren property to load the sub-module and its route definition
  • In the sub-module, keep the first path empty and load the sub-module's entry component (for example, nest-1 module will load the nest-1 component)

WORKING EXAMPLE

I hope this explanation was clear.

Answer №2

Upon implementing the changes suggested by Luca Regazzi's answer, I encountered an error in my production environment.

Error: Uncaught (in promise): Error: Runtime compiler is not loaded

Error: Runtime compiler is not loaded

It seems that when using AOT compilation, there is a different approach to dynamically loading modules as documented in this Bug Report on Angular/Angular-cli.

Rather than:

import { MyComponent } from './path/mycomponent.component';

...

loadChildren: () => MyComponent

The correct way is:

// no import

...

loadChildren: () => import('./path/mycomponent.component')
  .then(m => m.MyComponent)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Creating a new endpoint within the Angular2 framework using typescript

I am brand new to Angular2 and I would like to streamline my API endpoints by creating a single class that can be injected into all of my services. What is the most optimal approach for achieving this in Angular2? Should I define an @Injectable class sim ...

Jasmine reported that there were no specifications found in the Angular project written in TypeScript

I'm facing a frustrating issue with Karma and Jasmine in my Angular 9 project. Despite setting up the configuration files correctly, I keep getting a "No specs found" message when running ng test. I have tried various adjustments, including creating d ...

What is the best way to attach a value to an attribute of a web component in Angular?

In all honesty, I am quite new to Angular and still learning the ropes. Currently, I am faced with a debugging challenge related to one of the users encountering an issue with my web component library. Within this library, there is a custom element create ...

Ways to resolve the issue of the 'setConfirmDelete' property not being found on type 'JSX.IntrinsicElements' in React.js

index.tsx const setConfirmDelete = (state, close) => { return ( <Modal show={state} onHide={close}> <Modal.Header> <Modal.Title>Title</Modal.Title> </Modal.Header> <Modal.Body> 'T ...

Typescript React Union type

I have developed a Card component with two different variants: Wrapper and Dashboard. Each variant comes with its own set of props. export type DashboardProps = { variant: CardVariant.Dashboard, primaryText: string, secondaryText: string, icon: Ove ...

The function __WEBPACK_IMPORTED_MODULE_3_ionic_native__.a.open is returning an error

Is there a way to troubleshoot and resolve the following error: WEBPACK_IMPORTED_MODULE_3_ionic_native.a.open is not a function while utilizing the NishanthKabra/Ionic2_GoogleCalendar solution. I am interested in integrating Google Calendar into my Io ...

Problems related to TypeScript in a callback session

I am currently working on enhancing the API response by adding the unique identifier (id) property during the login process. I followed the recommendation to use callbacks from a discussion on Stack Overflow (Get User ID from session in next-auth client), ...

What is the best way to rekindle the d3 force simulation within React's StrictMode?

Creating an interactive force directed graph in React using D3 has been successful except for the dragging functionality not working in React StrictMode. The issue seems to be related to mounting and remounting components in ReactStrict mode 18, but pinpoi ...

Cannot trigger event ascn.onchange does not exist as a function

Need to trigger the onChange function and pass parameters within it. Here's what I have tried: setTimeout(function() { document.getElementById(input.key)?.onchange({}) }, 200); Encountering the following error message: cn.onchange is not a function ...

Tips for presenting the cards in a professional layout

After creating a group of cards in angular using a for loop, I encountered an issue: <div class="row"> <div *ngFor="let dev_data of data" class="col-3"> <div class="card shadow"> <div class="card-body ...

Angular 2: Executing a function after ngFor has completed

Within Angular 1, I crafted a personalized directive called "repeater-ready" to pair with ng-repeat for triggering a callback method upon completion of an iteration: if ($scope.$last === true) { $timeout(() => { $scope.$parent.$parent.$ ...

Angular 10: Unexpected Behavior with Observables

When I initially call addPost(), the observable behaves as expected with a 5-second delay. However, when I call it a second time, the data updates in the HTML without any delay. On the other hand, the same observable with deletePost() functions perfectly. ...

I encountered an issue while generating a crypto address on the Waves blockchain using the @waves/waves-crypto library in TypeScript

Encountering an issue with finding "crypto-js" in "@waves/waves-crypto". Despite attempts to uninstall and reinstall the module via npm and importing it using "*wavesCrypto", the error persists within the module's index.d.ts file. I am attempting to ...

loop failing to refresh element within array

Is there a way to update a specific property in every element of an array to match its index? I attempted the following approach: static reindexComponentsOnMultiplePages(components) { return components.forEach((el, idx) => (el.componentIndex = id ...

What is the best way to refresh a Component upon sending data to the server?

I'm in the process of developing a cross-platform application. I have a TabView Component that needs to update a tab after sending data to the server. During the initialization (ngOnInit) phase, I dynamically set the content of my tab. However, when I ...

Setting a value in the selectpicker of rsuitejs involves assigning a specific value to the

const _DATA = [{ code: 'code1', name: 'Jagger' },{ code: 'code2', name: 'Tigger' },{ code: 'code3', name: 'Lion' }] <SelectPicker data={_DATA.map(x => {return {label: x.n ...

Checking nested arrays recursively in Typescript

I'm facing difficulty in traversing through a nested array which may contain arrays of itself, representing a dynamic menu structure. Below is how the objects are structured: This is the Interface IMenuNode: Interface IMenuNode: export interface IM ...

Angular HTML is throwing an error related to object arrays

Is there a way to display only specific fields of an array? <div class="form-check" *ngFor="let periodo of filterPeriodos()"> <div>{{periodo.periodos | json}}</div> <input class="form-check-input mr- ...

The error at core.js line 4442: TypeError - Unable to access the 'trim' property of an undefined value

I encountered an issue with the 'trim' function in my Angular Node MySQL CRUD Application core.js:4442 ERROR TypeError: Cannot read property 'trim' of undefined at AdmissionListComponent.post (admission-list.component.ts:30) at Admissi ...

Repeating percentages displayed in a progress bar

I created a responsive progress bar, but the progress values are repeating. I only want the central value to be displayed. Any suggestions on how to fix this issue? DEMO <div id="tab1"> <dx-data-grid class="tableTask" [dataSource]="datas" ...