HeavenlyHost
HeavenlyHost

Reputation: 95

angular 2 RC4 create component

So here is the problem, I am attempting to create a new component from within a service that is injected within the App Component. I need the new component to be placed within the app component html tag not outside. The thing is I really do not want the app component to have to provide anything to the service I may need to inject the service into other places and hence not have it tightly coupled to the app component. So far I have created a DIV at the end of the app component html and then used @ViewChild to read the ViewContainerRef from this element located within the app component. This is then provided to the service via a function call so that it can make use of createComponent. This allows for the NEW component to be placed within the scope of the app component, not within the body. Unfortunately this is too dependant on the app component providing the ViewContainerRef. Any ideas of how I can create the new component as described.

Code Example

app.component.html

<app-component>
    <div #newCompHook></div>
</app-component>

app.component.ts

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

constructor(appService: AppService) {
   appService.setViewRef(this.newCompViewRef);
}

app.service.ts

private myViewRef;

constructor(private compiler: ComponentResolver){
    this.myViewRef = null;
}

public setViewRef(vr: ViewContainerRef): void {
    this.myViewRef = vr; // <-- DO NOT WANT TO DO THIS !!!
}

public createNewComp(childCmp: Type): void {
    if (this.myViewRef !== null){
        this.compiler.resolveComponent( childCmp ).then((compFactory:ComponentFactory) => this.myViewRef.createComponent(compFactory) )
    }
}

createNewComp is called by an external source and may or may not provide the childCmp type to be resolved.

So any ideas of how I can do this without needing to provide anything from the app component ???

Upvotes: 1

Views: 142

Answers (1)

lambdoa
lambdoa

Reputation: 1

If you need to have the viewContainerRef in your service that is the only solution... But it is not a good practice to generate HCI components in a service. It's the role of other components.

Let's take an exemple : your server send you a list of objects (a list of strings for exemple) and you want to generate a button for each string.

In your service you just manage the string list :

@Injectable()
export class MyService {
    private myModel : Array<String> = new Array();
    public get MyModel () : Array<String> {
      return this.myModel;
    }

    /// Assume you have method in the service to populate the model...
}

Then it's your component which generate the HCI :

export class AppComponent {
   /// Use dependency injection to get service :
   constructor (private _myService : MyService){}

    public get MyModel () : Array<String> {
      return this.myService.MyModel;
    }
}

Finally in your component template :

<div>
 <ul>
   <li *ngFor="let s of MyModel">
     <!-- Button with your model text -->
     <button>s</button>
   </li>
 </ul>
</div>

That is a better solution than generate the components in the service because just imagine you don't want buttons list but a togglebuttons list in your HCI, here you just have to change the HTML. The service is still the same, and the components typescipt part is still the same too !

Upvotes: 0

Related Questions