8

I'm working on a little project of mine in order to learn something more about Angular, but I really cannot figure out how to implement a multi-leveled routing.

I've read the documentation about the new release of the Router Component and also some other topics on StackOverlfow (first, second, third), but I cannot find a solution to my problem.

Let's consider the following app structure, without considering the Test and Test2 blocks.

App structure

And let's consider the components of my app as following:

main.ts

import { bootstrap }    from '@angular/platform-browser-dynamic';

import { MyAppComponent } from './my-app/my-app.component';
import { APP_ROUTER_PROVIDERS } from './my-app/my-app.routes';

bootstrap(MyAppComponent, [ APP_ROUTER_PROVIDERS ])
    .catch(err => console.error(err));

my-app.component.ts

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

@Component({
    selector: 'my-app',
    template: '<router-outlet></router-outlet>',
    directives: [ROUTER_DIRECTIVES],
})

export class MyAppComponent { }

my-app.routes.ts

import { provideRouter, RouterConfig } from '@angular/router';

import { HomeComponent } from './home/home.component';
import { LoginComponent } from './login/login.component';
import { SignUpComponent } from './sign-up/sign-up.component';

import { AdminRoutes} from './admin/admin.routes';

export const routes: RouterConfig = [
  { path: '', component: HomeComponent },
  { path: 'login', component: LoginComponent },
  { path: 'sign-up', component: SignUpComponent },
  ...AdminRoutes,
];

export const APP_ROUTER_PROVIDERS = [
    provideRouter(routes)
];

admin.component.ts

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

@Component({
    selector: 'admin',
    template: 'Hello I am ADMIN <br> <router-outlet></router-outlet>',
    directives: [ROUTER_DIRECTIVES]
})

export class AdminComponent { }

admin.routes.ts

import { RouterConfig } from '@angular/router';

import { AdminComponent } from './admin.component';
import { MainPageComponent } from './main-page/main-page.component';
import { SettingsComponent } from './settings/settings.component';

export const AdminRoutes: RouterConfig = [
  {
      path: 'admin',
      component: AdminComponent,
      children: [
        { path: 'main-page', component: MainPageComponent },
        { path: 'settings', component: SettingsComponent },
      ]
  }
];

main-page.component.ts

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

@Component({
    selector: 'main-page',
    template: 'Hello I am MAIN PAGE!!!'
})

export class MainPageComponent { }

settings.component.ts

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

@Component({
    selector: 'settings',
    template: 'Hello I am SETTINGS!!!'
})

export class SettingsComponent { }

When I try to use such a configuration nothing works anymore and the browser's console is full of errors.

This happens only when I add the children[...] in the admin.routes.ts, and I think the problems come in there.

  1. Could you give me any hint on how I can implemented properly, please?
  2. Am I missing anything?
  3. Is there a better way?

Thank you in advance for your help and I hope what I've written in the post it's helpful to understand my issue!

1 Answer 1

7

Angular router considers a route with children as a non-terminal route and routing happens to terminal routes only. Angular router expects route to have a default entry for path: ''.

To resolve this issue you should add a redirect from the parent route to one of the child routes.

export const AdminRoutes: RouterConfig = [
{
    path: 'admin',
    component: AdminComponent,
    children: [
        { path: '', redirectTo: 'main-page', terminal: 'true' },
        { path: 'main-page', component: MainPageComponent,
        { path: 'settings', component: SettingsComponent },
    ]
 }];

Edit: if using rc4 and router 3.0.0-beta2 they have renamed terminal to pathMatch. So update the redirect route as below:

{ path: '', redirectTo: 'main-page', pathMatch: 'full'},
Sign up to request clarification or add additional context in comments.

5 Comments

You made my day dude, thank you! Just a last question: By using your solution, when I try to load the /admin route, it also loads the /test. How can I tell to my app to load /test only when the user wants so?
It should not unless you have added it to be part of default route (terminal). Show me the updated router config for admin and below
I'm sorry I was wrong... You're right I can't do such a thing! Can I apply this concept to other sub-routers, in order to achieve n levels of routing? Is that a good practice?
Yes you can and you should
Thanks for the version with the updated router - really helped me out!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.