2

I've got a problem and I'm not sure what the issue is.

So I want to dynamically add components to another component I have using query params.

So I have the component dynamically being added but it doesn't work when I do it using a query string with the exact same name

so the route is set up like this

{
    path: 'tool-view/:tool',
    component: ToolViewerComponent
}

then In app.module I'm adding the component I'm trying to add dynamically to the entryComponents like so...

entryComponents: [
    CoolToolComponent
]

then In my toolViewerComponent I have this

import { Component, OnInit, ViewChild, ViewContainerRef, ComponentFactoryResolver } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

// Tool Components
import { CoolToolComponent } from '../tools/cool-tool/cool-tool.component';

@Component({
  selector: 'app-tool-viewer',
  templateUrl: './tool-viewer.component.html',
  styleUrls: ['./tool-viewer.component.scss']
})
export class ToolViewerComponent implements OnInit {

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

  constructor(
    private _resolver: ComponentFactoryResolver,
    public activatedRoute: ActivatedRoute
  ) { }

  ngOnInit() {
    // Resolvers
    const coolFactory = this._resolver.resolveComponentFactory(CoolToolComponent);
    const toolComponent = this.entry.createComponent(coolFactory);
  }
}

okay so this works, the component is added onto the page no problem now when I try to do this...

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

constructor(
  private _resolver: ComponentFactoryResolver,
  public activatedRoute: ActivatedRoute
) { }

ngOnInit() {
  this.activatedRoute.params.subscribe(params => {
    this.createComponent(params.tool);
  });
}

createComponent(tool) {
  const toolFactory = this._resolver.resolveComponentFactory(tool);
  const toolComponent = this.entry.createComponent(toolFactory);
}

but this doesnt work and I get the error

No component factory found for CoolToolComponent. Did you add it to @NgModule.entryComponents?

I'm not entirely sure whats going on here, but I think I might be the fact that in the createComponent(tool) the tool comes in as a string "CoolToolComponent" and not as the CoolToolComponent ??

But I'm not sure.

The only other way I can think of doing this is to use a bunch of if Statements.

if(params.tool = 'CoolToolComponent') {
    const hba1cFactory = this._resolver.resolveComponentFactory(Hba1cTracker);
    const toolComponent = this.entry.createComponent(hba1cFactory);
} etc..

and I would like to avoid doing that.

Any help would be appreciated!

Thanks

5
  • Yes you need to pass in a Class not a String. But why don't you use different sub-routes to load your component into the parent view? For instance: ` path: '', component: HomeComponent, children: [ { path: 'sub-route', component: SubComponent },` Commented May 29, 2018 at 7:38
  • Thats not my question, I know I could create childroutes but I want to add components dynamically to a single page Commented May 29, 2018 at 9:49
  • But wouldn't you achieve the same thing routing to a childroute instead of call a link with a query param? If you really want to load your components with the factory you should store your class types in a key value map and access it through your string param. Commented May 29, 2018 at 10:10
  • My situation is, I have a bunch of tools that already have components, those components are used elsewhere through the app. Now instead of making 17 new pages the base of the tools are pretty much the same so.. I can make one page and dynamically load in the tools depending on the route Commented May 29, 2018 at 20:29
  • How about creating an array which maps your dynamic components with corresponding params? Commented May 30, 2018 at 6:52

1 Answer 1

1

You can create an array holding your dynamic component set with routing params are key of corresponding components. Something like this:

import { Component } from '@angular/core';
...
import { ToolComponent} from './tool.component';

@Component({...})
export class ToolViewerComponent  {
  ...

  tools: Component[] = new Array();

  constructor() {
    // add more tools here...
    this.tools['tool'] = ToolComponent;
  }

  ngOnInit() {
  this.activatedRoute.params.subscribe(params => {
    let toolName = param.tool;
    this.createComponent(this.tools[toolName]);
  });
}

createComponent(tool: Component) {
  const toolFactory = this._resolver.resolveComponentFactory(tool);
  const toolComponent = this.entry.createComponent(toolFactory);
}

}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.