Angular 6: Can't get the child route to load in the router outlet.

3,934 views
Skip to first unread message

Adam Frank

unread,
Sep 22, 2018, 2:35:55 PM9/22/18
to Angular and AngularJS discussion

I have a project with file structure


app/
    (all the files that get automatically built)
    app-routing.module.ts
    components/
        layout/
            top/
            side/
            banner/
        pages/
            home/
            prehistory/
                prehuman/
                    australopithecine/
                    homininia/
                earlyHuman/
                    outOfAfrica/
                    agriculture/
            ancient/
                (several directories like in prehistory)
            post-classical/
                (several directories like in prehistory)

Each directory under pages/ was built in the CLI with

ng g c ___
so that it has all the usual files. I'm trying to build the router so that it reflects the directory structure with child routers, so I have in app-routing.module.ts the following code. Note that since I'm at the early stages I haven't fully written out all the children and their sub-children, I just wanted to get a small part of it built and tested before building out the rest.


app-routing.module.ts


import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from './components/pages/home/home.component';
import { PrehistoryComponent } from './components/pages/prehistory/prehistory.component';
import { AncientComponent } from './components/pages/ancient/ancient.component';

export const routes: Routes = [
{path:'', redirectTo:'/home', pathMatch:'full'}
{path:'home', component:HomeComponent,
children: [
{path:'prehistory', component:PrehistoryComponent},
{path:'ancient', component:AncientComponent},
]}
];

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

In my AppComponent I used header and other tags to control CSS styles, but the important part is that there's a portion of the screen reserved for the header, for the side, and then the content which is the part that changes based on the address.


app.component.html


<header>
  <app-top></app-top>
</header>
<aside>
  <app-side></app-side>
</aside>
<content>
  <router-outlet></router-outlet>
</content>

And the links are in the TopComponent.


top.component.html


<div><app-banner></app-banner></div>
<div id="breadcrumb">
<nav>
<a [routerLink]="['home']" routerLinkActive="active">Home</a>
<a (mouseover)="onHover()" [routerLink]="['./home','prehistory']" routerLinkActive="active">Prehistory</a>
</nav>
</div>

top.component.ts


import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({
selector: 'app-top',
templateUrl: './top.component.html',
styleUrls: ['./top.component.css'],
})
export class TopComponent implements OnInit {

constructor(private route: ActivatedRoute) { }

onHover = function() {
console.log(this.route.parent);
}

ngOnInit() { }
}

When I navigate to `localhost:4200` it loads correctly, but clicking `Prehistory` doesn't load anything and the address becomes `localhost:4200/#/home/prehistory` I thought it should be `localhost:4200/#/home/#/prehistory` but perhaps I have that wrong.  If I include a router outlet tag in the home or prehistory component then the prehistory page loads but it loads below the HomeComponent whereas I want it to replace the HomeComponent.


home.component.html


<p>
  home works!
</p>

prehistory.component.html


<p>
  prehistory works!
</p>

Using .forChild instead of .forRoot seems to break the page.

Sander Elias

unread,
Sep 23, 2018, 12:18:27 AM9/23/18
to Angular and AngularJS discussion

Hi Frank,


The syntax you should use to navigate to prehistory is: [routerLink]="['./home/prehistory']" things after the , are optional parameters usually.


Regards

Sander

Sander Elias

unread,
Sep 23, 2018, 12:19:45 AM9/23/18
to Angular and AngularJS discussion

Hi Frank,

I also noticed you used a <content> tag. I’m not sure that’s in place there, I would use a <main>

Regards
Sander

Adam Frank

unread,
Sep 23, 2018, 12:30:13 AM9/23/18
to Angular and AngularJS discussion
So I tried something like that before and it didn't fully work.  Now if I try it, not only it doesn't fix the problem but also it doesn't even load the Prehistory page at all when I click the link.

Changed the content tags, thanks for the heads-up, never heard of them before.

Sander Elias

unread,
Sep 23, 2018, 1:16:16 AM9/23/18
to Angular and AngularJS discussion
Hi Adam,

Can you put your sample on stackBlitz? If you have it on github, you can load the stackblitz from your repo.
I will fix your issue when you have done that. (I don't have the time available now to recreate the entire thing)

Regards
Sander

Sander Elias

unread,
Sep 23, 2018, 1:23:36 AM9/23/18
to Angular and AngularJS discussion

Hi Adam

I just noticed the prefix ., that’s probably the culprit. try [routerLink]="['/home/prehistory']" Also, check the baseUrl in your project. That might mess things up too but is normally good in its default state.

regards
Sander

Adam Frank

unread,
Sep 23, 2018, 3:37:37 PM9/23/18
to Angular and AngularJS discussion
I tried to get this on stackBlitz but for whatever reason when I load `stackblitz.com/axiomtutor/explain` it tells me there is no page.  I think maybe it got screwed up because I initially tried to load before I had pushed everything onto git, so it gave an error and now I don't think it's updating even though I have since pushed the whole project to GitHub.  Are you able to look at it directly on the GitHub page?  If so it's at


I removed the dots but the bug didn't change.

Adam Frank

unread,
Sep 23, 2018, 3:46:09 PM9/23/18
to Angular and AngularJS discussion
Oops, realized I should have loaded `stackblitz.com/github/axiomtutor/explain`, doing that now, it's taking a very long time.  Will post the results if and when I get them.

Sander Elias

unread,
Sep 24, 2018, 1:26:17 AM9/24/18
to Angular and AngularJS discussion
Hi Adam,

this will work:
export const routes: Routes = [
{
path: 'home',
children: [
{
path: '',
pathMatch: 'full',
component: HomeComponent
},
{ path: 'prehistory', component: PrehistoryComponent },
{ path: 'ancient', component: AncientComponent }
]
},
{ path: '', redirectTo: '/home', pathMatch: 'full' }
];

The way your routing was set up, meant that the home component would be in view all the time. if that was what you wanted, it needs its own router-outlet.

You could not run it in stackBlitz because of the included  node_modules and dist folder. If you put something to GitHub, you must exclude those folders or at least the node_modules.

Hope this helps,
Regards
Sander

Sander Elias

unread,
Sep 24, 2018, 2:07:05 AM9/24/18
to Angular and AngularJS discussion
Hi Admin,

Also, I made a PR for your repo, so you can see the diff, and why the stackBlitz didn't work for you.

Regards
Sander

Adam Frank

unread,
Sep 29, 2018, 12:56:51 AM9/29/18
to Angular and AngularJS discussion
So it took me a long time to get around to this, but I finally implemented the changes.  A few issues persist:  First, this fix loads "Prehistory" underneath "Home" whereas I wanted Prehistory to replace Home. 

The second issue is that when you click on Prehistory and hover over the link, it prints out that the router parent is null.  I was hoping to make it so that the router reflects the location where the user has navigated to--so if you're in Prehistory, the router reflects that, and its parent should be Home.  Similarly if you were in a sub-section of Prehistory, like Prehumans, then the router's path would be to Prehuman, and its parent would be to Prehistory, and the parent of that would again be Home.

I was told to use hash routes to try to accomplish this behavior, hence why my code had that before the fix.
Reply all
Reply to author
Forward
0 new messages