We have a requirement where depending on a static/global setting which will be set depending on the customer they want a different component to load for a route. The reason being they want slightly different functionality for a part of the application so we are going to write a component for each that caters for their scenarios. Is there a way to choose the component for a route dynamically/at runtime and keep the same route/url. Below is a simplified example of what we would like to achieve:
Component1:
@Component({
selector: 'customeronecomponent',
templateUrl: './customeronecomponent.component.html'
})
export class CustomerOneComponent implements OnInit {
}
Component2:
@Component({
selector: 'customertwocomponent',
templateUrl: './customertwocomponent.component.html'
})
export class CustomerTwoComponent implements OnInit {
}
Route:
{ path: 'home', component: CustomerComponentProvider },
In this instance the CustomerComponentProvider will internally check the setting and either return CustomerOneComponent or CustomerTwoComponent.
In angular2/4 is that the best way to do this or is it better to have a single component and on that component load the right component, the downside I see there is we would have three components instead of two for each route we need this.
The Router-Outlet is a directive that's available from the router library where the Router inserts the component that gets matched based on the current browser's URL.
In Angular, the best practice is to load and configure the router in a separate, top-level module. The router is dedicated to routing and imported by the root AppModule . By convention, the module class name is AppRoutingModule and it belongs in the app-routing.module.ts in the src/app directory.
You may already be doing this internally in your CustomerComponentProvider, but in case not - there is Dynamic Component Loader.
The example given in the docs is a bit busy, so here's a dumbed-down version: Plunker
Essentially, a wrapper is used to switch between components depending on config string passed in, or retrieved from a service.
import { Component, Input, OnChanges,
ComponentFactoryResolver, ViewContainerRef } from '@angular/core';
import { Component1 } from './component1';
import { Component2 } from './component2';
@Component({
selector: 'component-wrapper',
template: `<div></div>`
})
export class ComponentWrapper implements OnChanges {
@Input() config;
private componentMap = {
component1 : Component1,
component2 : Component2,
}
constructor(
private viewContainerRef: ViewContainerRef,
private componentFactoryResolver: ComponentFactoryResolver
) {}
ngOnChanges() {
this.setComponent();
}
setComponent() {
const componentFactory = this.componentFactoryResolver
.resolveComponentFactory(this.componentMap[this.config]);
this.viewContainerRef.clear();
this.viewContainerRef.createComponent(componentFactory);
}
}
You can update the router configuration whenever you want, so depending on the setting you have you can add or update a route config to resolve to the component that you need.
Have a look at the config property or maybe more suited for this, the resetConfig method on the Router. You could inject the Router in the component where you want to handle this and update the routes according to the global setting that you have.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With