Join the Stack Overflow Community
Stack Overflow is a community of 6.5 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

In creating dynamic components in angular 2, I found out that this process requires ViewContainerRef in order to add newly created component to DOM.

Angular 2 dynamic tabs with user-click chosen components https://www.lucidchart.com/techblog/2016/07/19/building-angular-2-components-on-the-fly-a-dialog-box-example/

And in passing input and output to those dynamically created components, I found the answer in the second link above and here: https://codedump.io/share/kQakwDKNu0iG/1/passing-input-while-creating-angular-2-component-dynamically-using-componentresolver

However, if I were to create a service named shape.service that contains functions returning different shape components with some input like bgColor, I don't know how this service will create a component without specifying DOM location, and how the container-component receives this returned component (probably its type will be ComponentRef) from the service and injects it to the DOM container-component specifies.

For example, a service contains a function :

getCircle(bgColor:string): ComponentRef<Circle> {
    let circleFactory = componentFactoryResolver.resolveComponentFactory(CircleComponent);
    let circleCompRef = this.viewContainerRef.createComponent(circleFactory);
    circleCompRef.instance.bgColor = bgColor;

    return circleCompRef;
}

First question rises here, how do I make this.viewContainerRef point to no where for the meantime? The reason why I'm importing viewContainerRef is to create component dynamically.

Second question is after container-component receives input-specificcomponentRef from the service, how will it inject to its DOM?

Thanks in advance!

UPDATE: I think my question above wasn't specific enough. I'm in a situation where:

  1. A parent component calls the service and gets the componentRef/s,
  2. Creates an object including componentRef/s together with some other data and stores those created object/s into array
  3. Passes it to its children as input,
  4. And let each child inject componentRef to its DOM and use rest of the data in the object in other way.

That means the service calling component has no idea where those componentRef will get injected. In short, I need independent component objects that can be injected to anywhere, anytime I want.

I'm reading the rumTimeCompiler solution several times already but I don't really get how that really works. It seems like there's too much work compared to component creation using viewContainerRef. I'll dig into that more if I find no other solution...

share|improve this question
    
NOTE: also check solution with RuntimeCompiler stackoverflow.com/q/38888008/1679310 – Radim Köhler Aug 31 '16 at 5:16

Maybe this plunker will help you: https://plnkr.co/edit/iTG7Ysjuv7oiDozuXwj6?p=preview

As far as i know, you will need the ViewContainerRef inside of your service. But the component calling your service can add it as an parameter, like this:

(just a the service.. see plunker for full working example)

import { Injectable, ViewContainerRef, ReflectiveInjector, ComponentFactoryResolver, ComponentRef } from '@angular/core';

import { HelloComponent, HelloModel } from './hello.component';

@Injectable()
export class DynamicCompService {

  constructor (private componentFactoryResolver: ComponentFactoryResolver) { }

  public createHelloComp (vCref: ViewContainerRef, modelInput: HelloModel): ComponentRef {

    let factory = this.componentFactoryResolver.resolveComponentFactory(HelloComponent);

    // vCref is needed cause of that injector..
    let injector = ReflectiveInjector.fromResolvedProviders([], vCref.parentInjector);

    // create component without adding it directly to the DOM
    let comp = factory.create(injector);

    // add inputs first !! otherwise component/template crashes ..
    comp.instance.model = modelInput;

    // all inputs set? add it to the DOM ..
    vCref.insert(comp.hostView);

    return comp;
  }
}
share|improve this answer
    
wasnt what? :) pls clarify. – mxii Sep 1 '16 at 5:42
    
Oops, I pressed enter before finishing my sentence :( Sorry for removing the "green check" on your answer. I thought this was what I needed but I found out my question wasn't specific enough... Do you mind checking the update and giving another solution if possible? Sorry for the trouble – Dangular Sep 1 '16 at 5:57
    
I dont know if its possible to create a component just like that way, cause the component needs to know which components, services and directives it could use..i am currently searching for a solution, too. maybe we will found something .. keep this thread up! :) – mxii Sep 2 '16 at 6:52
    
Thanks for your effort! I still have no idea why it is not possible to create component instance without specifying its viewContainer. If that's possible, I believe it'll be easier to move, delete, or add existing component instance easily from one container to another. It's somehow possible to do with componentFactory but it becomes hard to implement if that component requires input/output. I tried to look for why it is a "must" to specify viewcontainer in creating component instance, but I still don't know why. I hope someone would at least give an answer to that... – Dangular Sep 3 '16 at 5:18

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.