【问题标题】:Angular - Factory components inside forAngular - 内部的工厂组件
【发布时间】:2020-05-06 10:41:04
【问题描述】:

我正在使用 Angular Gridster 2 构建组件仪表板。这些组件,我们称之为小工具,可能有不同的选择器(所以组件),但我在后端/数据库调用后的运行时知道它。

除此之外,网格的代码在 Angular 库中,但要渲染的组件存储在主应用程序中。

所以我在想这种方法:

库组件接收几个输入参数。一个关于 Dashboard 的对象(带有标题等),一个要显示的项目列表(实现 GridsterItem 接口的对象),以及调用者实现以动态构建组件的 factory_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>

调用者组件

调用者在其 HTML 中使用 Library 组件传递三个参数。 它调用数据库以获取仪表板的数据和它在实现 GristerItem 的类中转换的小部件列表。此类具有一个属性,即相对于该小部件的组件的“选择器”。

<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;
}

如您所见,Library 组件使用工厂函数将 Item 返回给调用者,此路由效果很好。

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

在控制台中,我有调用者在 grid_items 中传递的所有项目(我知道它有点复杂,因为调用者收到了它传递的小工具)

现在我需要用 item 对象内的选择器渲染相关组件。

结果必须是:

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

例如

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

MyFooComponet 将是一个带有

的组件
@Input() data : Objects = {};

接收该小工具的 DB 数据属性,用于解释要做什么。

【问题讨论】:

  • Angular 不希望你手动创建组件,你应该使用@ContentChild。看棱角材料。他们使用这种方法,这是我们拥有的最干净的方法。
  • 我不明白如何使用 contentchild 装饰器。组件必须在运行时构建。在那之前,我没有使用 ContentChild 寻找任何组件。

标签: javascript angular


【解决方案1】:

这是通过选择器创建元素的最简单方法。

<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;

  ...
}

如果您需要创建更多元素类型,或者不希望它们成为捆绑包的一部分,您可能需要使用 Angular Material Portal (https://material.angular.io/cdk/portal/overview)

【讨论】:

  • 我无法绑定 CallerComponent 中的每个小工具。我现在正在尝试使用 Portal,但我不知道如何使用。它总是用来重新加载相同的组件,但我必须创建多个 portalHost 每个具有不同组件的...
  • 每次更改组件时,您都需要创建新门户并销毁旧门户
  • 在我的情况下,我需要为 *ngFor 中的每个组件构建一个门户,然后用 Component 填充它,但我不知道如何。在站点上的示例中,他们重复使用相同的门户来更改内容。我不需要更改,因为我同时需要页面中的所有组件。
  • 如果您需要多个门户,您可以使用 ngForngSwitch 或多个门户,由您决定...
猜你喜欢
  • 1970-01-01
  • 2020-06-12
  • 2018-11-21
  • 1970-01-01
  • 2017-04-18
  • 1970-01-01
  • 1970-01-01
  • 2016-04-21
  • 1970-01-01
相关资源
最近更新 更多