Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 Load Different Component for Route Depending on Global Setting

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.

like image 460
user351711 Avatar asked Aug 11 '17 08:08

user351711


People also ask

Which directive is used to display the component matched by routes?

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.

Which modules should be imported for Angular routing?

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.


2 Answers

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);
  }

}
like image 142
Richard Matsen Avatar answered Sep 29 '22 22:09

Richard Matsen


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.

like image 45
Adrian Fâciu Avatar answered Sep 29 '22 22:09

Adrian Fâciu