4

I am currently trying to implement an angular 2 application with multiple navigation levels. The problem is that my child components cannot find a router outlet when it is not explicitly declared in the parent component from my routes.

This is the error message i get:

Unhandled Promise rejection: Cannot find primary outlet to load 'EditUserComponent'

I want something like an edit or detail view which shows instead of the list view when i click on a button or link. The views are embedded in a template layout which has navigation structure and provides a router outlet for the content. I also want to target this router-outlet with all my views. I already tried using named outlets but without success. I use a breadcrumb component to show the current route, so i cannot make the edit/detail view to be a sibling of my list component.

To make it more clear, i made a plunker demo:

https://embed.plnkr.co/XXxADnS7q8FCfF4W84tS/

How can i solve the outlet issue and target the layout's router-outlet from child components?

kaischo
  • 148
  • 1
  • 8

1 Answers1

1

One solution could be to simply wrap everything in your UsersComponent template, apart from the router outlet in a div. Then hide/show that div accordingly if the component has children (UsersEditComponentin this case) or not.

What this does is allowing your router to keep the correct parent/child hierarchy between UsersComponent and UsersEditComponent, while still ONLY showing the UsersEditComponent content when that route is activated.

This is an implementation of UsersComponent that does exactly that:

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

@Component({
  template: 
  `<div *ngIf="!hasChildren">
    User 1 <button md-icon-button (click)="editUser(1)">edit</button><br/>
    User 2 <button md-icon-button (click)="editUser(2)">edit</button>
  </div>
  <router-outlet></router-outlet>
  `
})

export class UsersComponent implements OnInit {
  private hasChildren: bool;
  constructor(private router: Router, private route:ActivatedRoute) { }

  editUser(id) {
    this.router.navigate(['users/edit', id]);
  }

  ngOnInit() {
    this.hasChildren = false;
    this.router.events.filter(event => event instanceof NavigationEnd).subscribe(event => {
      this.hasChildren = this.route.children.length > 0;
    }
  }
}
Fredrik Lundin
  • 8,006
  • 1
  • 29
  • 35
  • 1
    That's exactly the problem i'm facing. When i add the router-outlet there, it will work, but it also displays the list above my edit form. i want my edit form to replace the list. – kaischo Feb 14 '17 at 11:28
  • @kaischo - Sorry, misunderstood you. Updated my answer! – Fredrik Lundin Feb 14 '17 at 11:50
  • Thanks again for your help, but this produces another problem i haven't included in the plunker example, but explained in my question post: My breadcrumbs which also rely on the routes won't work anymore. It would show something like this: Home -> Users and when i click on edit, it would show: Home -> Edit but it should be: Home -> Users -> Edit – kaischo Feb 14 '17 at 12:45
  • 1
    @kaischo, argh, sorry for sloppy reading :/. How does your `breadcrumb component` work? Does it just parse the url? If so, you can keep the routes as siblings, and just change the path from "edit:id" to "users/edit:id". – Fredrik Lundin Feb 14 '17 at 13:06
  • 1
    @kaischo, I update the answer anyway, to better align with what you are asking for. If this doesn't work because of your `breadcrumb component`, let me know – Fredrik Lundin Feb 14 '17 at 13:09
  • thanks for the update, i will try it out. I also updated the plunker with the breadcrumb. Note that the breadcrumb component comes with the admin template i'm using. So i do not want to tinker with it, if it isn't absolutely necessary to achieve what i want. – kaischo Feb 14 '17 at 13:21
  • 1
    @kaischo, thanks for the update of the plunkr. Turns out that breadcrumb is not parsing the url, but actually looks at the parent/children hierarchy - meaning my provided solution won't work. I will look into this later if it hasn't been solved already by then – Fredrik Lundin Feb 14 '17 at 13:25
  • Thanks! I was hoping for something more elegant, but this one works. The breadcrumb in plunker shows some odd behavior, but it should work in my project. – kaischo Feb 14 '17 at 15:23
  • @kaischo, I agree, there might be a more elegant solution. But this one should do the job until then. I also noticed the breadcrumb thing, but inspecting the actual logic in the breadcrumb component shows correct routes – Fredrik Lundin Feb 14 '17 at 15:57
  • @kaischo, do you have a final solution for this? I use the same admin template and I'm experiencing the same problem. I don't want to rewrite breadcrumbs component. Thank you – Dimonina Oct 23 '17 at 16:53