2
votes

I would like to add a <router-outlet name="param"></router-outlet> runtime.

With this code new RouterOutlet(this.parentOutletMap, this.rox, this.resolver, 'test');, router-outlet is added but when I call the route there is an error

"zone.js:357 Error: Uncaught (in promise): Error: Cannot find the outlet test to load 'AuxComponent'"

Trying to dynamically add a router-outlet in the main AppComponent, everything works correctly, the error is only in lazy loaded modules.

It seems that this.router.navigateByUrl and this.router.navigate, only use the parent outlet map instead of the child map.

enter image description here

Plnkr: http://plnkr.co/edit/0W5oZuCTE4dvkNhbvs52?p=preview

GitHub: https://github.com/fabriziodebortoli/dynamic-routing/

Code:

app.routing

export const appRoutes: Routes = [
    { path: '', component: HomeComponent },
    {
        path: 'page',
        loadChildren: () => new Promise(function (resolve) {
            (require as any).ensure([], function (require: any) {
                resolve(require('../pages/page.module').default);
            });
        })
    }
];

page.module

export const routing: ModuleWithProviders = RouterModule.forChild([
  { path: '', component: PageComponent },
  {
    path: 'wrap', component: PageComponent, children: [
      { path: 'test', component: AuxComponent, outlet: 'test' }
    ]
  },
]);

@NgModule({
  imports: [ CommonModule, FormsModule, routing],

  // added after Günter comment
  // entryComponents: [RouterOutlet], RouterOutlet is not a Component
  entryComponents: [OutletComponent],

  declarations: [PageComponent],
  exports: [PageComponent]
})
export default class PageModule {}

page.component

@Component({
    template: `Page 
        <hr>
        <button (click)="createRouterOutlet('test')">add</button>
        <button (click)="go()">go</button>
        <div #rox></div>`
})
export class PageComponent implements OnInit {

    @ViewChild('rox', { read: ViewContainerRef }) rox: ViewContainerRef;

    constructor(private router: Router,
        private parentOutletMap: RouterOutletMap,
        private resolver: ComponentFactoryResolver
    ) { }

    ngOnInit() {
        console.info(this.parentOutletMap);
    }

    createRouterOutlet(name: string) {
        // commented after Günter comment
        // let ro: RouterOutlet = new RouterOutlet(this.parentOutletMap, this.rox, this.resolver, name);
        // console.info(this.parentOutletMap);

        // added after Günter comment
        let factory = this.resolver.resolveComponentFactory(OutletComponent);
        let cmpRef = this.ros.createComponent(factory);
        console.info(cmpRef);
    }

    go() {
        this.router.navigateByUrl('/page/wrap/(test:test)');
    }
}

Edit: I tryied to wrap RouterOutlet with a custom component OutletComponent but I have the error message "Cannot find the outlet test to load 'AuxComponent'" yet

outlet.component

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

@Component({
  selector: 'app-outlet',
  template: `<router-outlet [attr.name]="name"></router-outlet>`
})
export class OutletComponent{
  private name: string = 'test';
}
1

1 Answers

2
votes

You can't create a component with new, this only creates an instance of the components class but without anything that actually makes it an Angular2 component.

let factory = this.componentFactoryResolver.resolveComponentFactory(RouterOutlet);
this.cmpRef = this.rox.createComponent(factory)
/// this.comRef.instance... to access the router outlet instance