Chris Tarasovs
Chris Tarasovs

Reputation: 695

Angular 2 | Typescript | Mapping an string to a component name and return component

I got list of components that I would like to replace on certain conditions:

List of navigation components:

import {navigationDefaultComponent} from '';
import {navigationSmoothComponent} from '';
import {navigationMobileComponent} from '';

navigations: [
{component: navigationDefaultComponent},
{component: navigationSmoothComponent},
{component: navigationMobileComponent},
]

I have an object that comes from API and tel's me what component I should show

const X = {
name: 'John Smith',
navigation: 'navigationDefaultComponent'
}

I have done it this way, as I can't store the component in the api. The API can not return me a component. If there is a way please do let me know. So my goal is is to have a const that will go through navigation object and based on x.navigation string will map and return me the component.

const nav = ????

Upvotes: 1

Views: 2350

Answers (1)

Shubham Gangpuri
Shubham Gangpuri

Reputation: 431

Well, this is a typical situation. You would need to make one of your component to listen to ** route and then use dynamic component loading. https://angular.io/guide/dynamic-component-loader

You can create an array having string and Component

let mapping = [
    {'name':'name1', 'component':Component1},
    {'name':'name2', 'component':Component2},
    {'name':'name3', 'component':Component3},
    {'name':'name4', 'component':Component4},
    {'name':'name5', 'component':Component5},
];

Please Note that Component1, Component2 are direct reference to the Component and not their string representations.

Create a directive, to be included in your AppComponent

import { Directive, ViewContainerRef } from '@angular/core';
@Directive({
    selector: '[app-directive]',
})
export class AppDirective {
    constructor(public viewContainerRef: ViewContainerRef) { }
}

Include the directive in your template

<ng-template app-directive></ng-template>

Get the reference to your directive in ts file

@ViewChild(AppDirective) appDirective: AppDirective;

Now load the desired component after getting the response from the API

// let's assume name1 is what API returned
let component = this.mapping['name1'];
let componentFactory = this.componentFactoryResolver.resolveComponentFactory(mapping[component);
let viewContainerRef = this.appDirective.viewContainerRef;
viewContainerRef.clear();

let componentRef = viewContainerRef.createComponent(componentFactory);

I hope this solves your problem...

Upvotes: 1

Related Questions