Hussain
Hussain

Reputation: 296

How to dynamically add routes with components from a dynamically loaded module

I have a dynamic component:

dynamic-component.module.ts

@NgModule({
  imports: [
      DynamicComponentRoutingModule,
      FormsModule,
      CommonModule,
      FormsModule,
  ],
  declarations: [
      DynamicComponent1,
      DynamicComponent2,
  ],
  exports: [DynamicComponent1,DynamicComponent2]
})
export class DynamicComponentModule {
}

And its routing:

dynamic-component.routing.ts

const routes: Routes = [
    {
        path: '',
        children: [
            {   
                path: 'dynamicComponent1',
                component: DynamicComponent1
            },
            {
                path: 'dynamicComponent2',
                component: DynamicComponent2,
            }
        ]
    }
];

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

I packaged this module into an angular package (using ng-packagr), and inside my app.component.ts I load it dynamically:

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

constructor(private router: Router, private _compiler: Compiler, private _injector: Injector, private route: ActivatedRoute) {
}

loadModule(path: string) {
    System.import(path).then((module) => {
        console.log(module);
        this._compiler.compileModuleAndAllComponentsAsync(module.DataTypesModule)
            .then((compiled) => {
                const m = compiled.ngModuleFactory.create(this._injector);
                const factory = compiled.componentFactories[0];
                if (factory) {
                    const cmp = factory.create(this._injector, [], null, m);
                    this.cmpRef = this.vc.createComponent(factory);
                }
            })
    });
}

As you can see, I've loaded the DynamicComponentModule and set the view in app.component to the first component in the DynamicComponentModule which happens to be DynamicComponent1.

The problem is when I want to navigate to DynamicComponent2 from DynamicComponent1. How to do that?

Edit:

Here is a plnkr that will show you the problem: https://embed.plnkr.co/rRCQx1N6nJvr0gBERINs/

Upvotes: 3

Views: 7738

Answers (1)

Max Koretskyi
Max Koretskyi

Reputation: 105537

You don't need to manually load and compile the module. You can use resetConfig API together with loadChildren. See the plunker.

Here is the relevant code:

loadModule() {
    this.router.resetConfig([
        ...this.router.config,
        {
            path: 'dynamicModule',
            loadChildren: './dynamic-component.module.ts#DynamicComponentModule'
        }
    ]);

    this.router.navigateByUrl('dynamicModule/dynamicComponent1');

You also need to add router-outlet to the my-app template:

@Component({
    selector: 'my-app',
    template: `
    <div>
      <h2>Hello {{name}}</h2>
      <router-outlet></router-outlet>
    </div>

And remove dynamicModule part from DynamicComponentRoutingModule:

const routes: Routes = [
    {
        path: 'dynamicComponent1',
        component: DynamicComponent1
    },
    {
        path: 'dynamicComponent2',
        component: DynamicComponent2,
    }
];

Upvotes: 1

Related Questions