简体   繁体   中英

Dynamic components inside ngFor

I am converting an angular 1 application to angular 2. I have the dynamic directives working in angular 1 in a ng-repeat. I went off of this plunker http://plnkr.co/edit/ET3LZhXBRjwIsbKVIwxm?p=preview

<tr ng-repeat="p in people">
     <td dynamic-directive="p.dir" blah="p"></td>
</tr>

from this question : Angularjs dynamic directive inside ngrepeat

Is it possible to do the basically the same thing with angular 2? My data model will tell me what component to use and what data to pass in to the component.

Edit: So my use case is: My main page on my site can have 10 different widgets and each widget is a different component - currently a directive in angular 1. Each component needs different data. The components can be in any order depending on how the site admin adds them in the database. I get the data from an API. In the data structure, there is a one to many: component > data. I need to loop through the data and add the components dynamically based on the component name from the data set. The data structure looks something like this.

"Topics":[
         {
            "component":"header",
            "Slug":"fake-slug",
            "URL":"some-image"
         },
         {
            "component":"standardcontent",
            "Slug":"fake-slug",
            "URL":"some-image"
         },
         {
            "component":"playlist",
            "PlayLists":[
               {
                  "CONPlaylistID":"22",
                  "description":"fake-description",
                  "image":"fake-image"
               },
               {
                 "CONPlaylistID":"22",
                  "description":"fake-description",
                  "image":"fake-image"
               }
            ]
         }
   ]

Thanks in advance

Directives can only be added by static HTML that matches the directive selector and there is no other mechanism to depend directive instantiation on.

You can use two similar elements where one matches the directive selector and the other doesn't and switch between them:

<tr *ngFor="let p of people">
  <td *ngIf="doAddDirective" dynamic-directive="p.dir" blah="p"></td>
  <td *ngIf="!doAddDirective" blah="p"></td>
</tr>

If it's about components instead of directives this might be what you want Angular 2 dynamic tabs with user-click chosen components

update Some explanation what <dcl-wrapper> does:

There are two main things, the rest is only to wrap it in a component for easier reuse.

The first is the ViewContainerRef and how to get it. This defines where the dynamically component will be added. You can either inject ViewContainerRef then the dynamically component will be added below (not inside) the current component
or you can acquire it from an element in the template of the current component using @ViewChild(..., {read: ViewContainerRef}) , then the dynamically added element will be inserted below that element.

The 2nd part is resolveComponent() with target.createComponent() that is the code that actually inserts the dynamic component.

The dcl-wrapper component is to make it easy to declaratively add dynamic components. Just add

<dcl-wrapper [type]="item.type"></dcl-wrapper>

to your template (assuming item is from *ngFor referring to an item of your JSON).

This will add a <dcl-wrapper></dcl-wrapper> component to your component and the <dcl-wrapper> will then add the dynamic component returned by item.type inside itself. The other code in <dcl-wrapper> is for when item.type changes to remove the previously added dynamic component and add the one item.type now refers to.

hint The dynamic component item.type needs to be a type reference not a string name. Therefore you need a way to get the component type from the name. You could provide a global service that returns the type from the name. You would need to maintain the mapping manually. There are ways to get the type from a name string imperatively in TypeScript but I haven't found the SO question/answer where this is explained.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM