简体   繁体   中英

Angular - Factory components inside for

Im using Angular Gridster 2 to build a Dashboards of components. These components, we call gadgets, may have different selector (so component) but I know it at runtime after a backend/database call.

Other than this, the code of the grid is inside an Angular Library but the components to be rendered are stored in the main application.

So I was thinking this approach:

The Library Component receives several input parameters. An object about the Dashboard (with title etc...), a list of Item to display (objects that implements GridsterItem Interface), and a factory_component the caller implements to build component dynamically.

LIBRARY DASHBOARD COMPONENT:

export class DashboardComponent implements OnInit {

  @Input() dashboard  : D3AbstractDashboard = new D3AbstractDashboard();
  @Input() gadgets    : GridsterItem[]      = [];
  @Input() factory_component : Function      = undefined;

...
}

<gridster [options]="options">
  <gridster-item *ngFor="let item of gadgets" [item]="item">
       {{ factory_component(item) }}
  </gridster-item>
</gridster>

CALLER COMPONENT

The caller use the Library component in its HTML passing the three parameters. It makes the calls to database to get the dashboard's data and the list of widget that it converts in the Class that implements GristerItem. This class has a property that is the "selector" of component relative to that widget.

<dashboard
   [dashboard]          = "dashboard"
   [gadgets]            = "grid_items"
   [factory_component]  = "factoryComponent"
>

</dashboard>

class MyApGristerItem implements GristerItem
...
constructor(gadget: Gadget)
{
        this.x          = gadget.x;
        this.y          = gadget.y;
        this.cols       = gadget.cols;
        this.rows       = gadget.rows;
        this.selector   = gadget.selector; //for example my-foo-component
        this.data       = gadget .data;
}

As you can see, the Library component return the Item to the caller using factory function and this route works great.

//Caller Component
factoryComponent(item)
{
    console.log(item);
}

In console I have all the items the caller has passed inside the grid_items (I know its a bit tricly becase the caller recieves the gadget it has passed)

Now what I need is to render the relative component with the selector inside the item object.

Ipotetically the result has to be:

<item.selector [data] = "item.data"> </item.selector>

For example

<my-foo-component  [data] = "item.data"> </my-foo-component>

MyFooComponet will be a component with an

@Input() data : Objects = {};

that receives the DB data property for that gadget that explains what to do.

This is the easiest way to create an element by a selector.

<dashboard 
 [dashboard]="dashboard"
 [gadgets]="grid_items"
 [ngSwitch]="componentTag"
>
  <gadget1 *ngSwitchCase="'gadget1'"></gadget1>
  <gadget2 *ngSwitchCase="'gadget2'"></gadget2>
  <gadget3 *ngSwitchCase="'gadget3'"></gadget3>
</dashboard>
export class DashboardComponent implements OnInit {

  @Input() dashboard: D3AbstractDashboard = new D3AbstractDashboard();
  @Input() gadgets: GridsterItem[] = [];
  @ContentChild() component?: Gadget;

  ...
}

If you need to create much more elements types, or don't want them to be part of the bundle you might want to use Angular Material Portal ( https://material.angular.io/cdk/portal/overview )

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