有没有办法在另一个组件中使用可变 Angular 组件,并将数据传递给该可变组件?

Posted

技术标签:

【中文标题】有没有办法在另一个组件中使用可变 Angular 组件,并将数据传递给该可变组件?【英文标题】:Is there a way to use a variable Angular component inside another component, and also pass data to that variable component? 【发布时间】:2021-07-17 03:57:47 【问题描述】:

我想要什么

假设 component2 是我希望能够在其中使用可变组件的组件。 举个例子,我们将使用的变量组件是component1。

component1.html: <div>Hi, I'm comp 1. Data: data</div>

component2.html:<div>Hi, I'm comp 2. Variable component: <variableComponent [data]="data"></variableComponent></div>

component2在某处的使用:<component2 [variableComponent]="component1" ></component2>

我要做什么

我正在关注 Angular 可扩展表格示例,其中可以单击每一行,使其展开以显示有关该行的详细信息。 https://material.angular.io/components/table/examples#table-expandable-rows

我已经制作了一个可以向其中传递数据的通用表格组件,并且我向其中添加了可扩展的行,但我也希望能够向其中传递一个详细信息组件,以便我们的开发人员可以为不同的对象制作不同的细节组件,以便我们可以将这些细节组件用于不同的表格。 (即,您可以制作一个元素详细信息组件,如果您正在制作一个元素表,就像在链接的示例中一样,然后将该组件传递给表格组件,则可以使用该组件)

我尝试使用 [innerHTML],这样我就可以传递一个可变的 HTML 字符串来呈现为详细信息面板,这样我就可以很容易地粘贴一个组件和参数。但它看起来不像在工作,可能是因为 [innerHTML] 正在跳过 Angular 所做的一些事情。

table-component html(您可能不需要阅读此内容来回答问题):

<mat-table class="lessons-table mat-elevation-z8" [dataSource]="matData" matSort [matSortActive]="tableKeys[0]" matSortDirection="asc" matSortDisableClear multiTemplateDataRows>
  <ng-container *ngFor="let key of tableKeys;" [matColumnDef]="key" >
    <mat-header-cell *matHeaderCellDef mat-sort-header> dataKeysToHeadersDictionary[key]</mat-header-cell>
    <mat-cell *matCellDef="let row">row[key]</mat-cell>
  </ng-container>

  <ng-container [matColumnDef]="'expandButtonColumnDef'">
    <mat-header-cell *matHeaderCellDef>:</mat-header-cell>
    <mat-cell *matCellDef="let row">
      <span  (click)="expandedRow = expandedRow === row ? null : row">::</span>
    </mat-cell>
  </ng-container>

  <ng-container [matColumnDef]="'expandedDetail'">
    <mat-cell class="detailCell" *matCellDef="let row;" [attr.colspan]="tableKeys.length">
      <div class="detailCellDiv" [@detailExpand]="row == expandedRow ? 'expanded' : 'collapsed'">
        <!-- vvv THIS IS THE IMPORTANT ROW vvv -->
        <div [innerHTML]="getRowDetail(row)"></div>
        <!-- ^^^ THIS IS THE IMPORTANT ROW ^^^ -->
      </div>
    </mat-cell>
  </ng-container>

  <mat-header-row *matHeaderRowDef="tableKeys.concat('expandButtonColumnDef')"></mat-header-row>
  <mat-row *matRowDef="let row; columns: tableKeys.concat('expandButtonColumnDef')"></mat-row>
  <mat-row class="detailRow" *matRowDef="let row; columns: ['expandedDetail']"></mat-row>
</mat-table>

表格组件打字稿:

// Right now, this is returning a static string with html to use the account-details component
// But eventually I want this to be a dynamic or variable string so I can use whatever component I give to the table-component
getRowDetail(row): any 
  return '<app-account-details style="display: flex;" [account]="row"></app-account-details>';

我想一种解决方法是制作一个通用详细信息组件,然后在 html 中放置一个 ngSwitch,其中包含我最终制作的每个详细信息组件,但这是一种解决方法。

编辑:解决方法

所以,问题是我希望能够将组件 1“传递”到组件 2,但也希望能够将数据从组件 2 传递到组件 1。 ng-content 似乎不允许我这样做,所以我创建了一个通用变量组件,您可以指示它显示您想要的任何组件,并将数据也传递给它。

通用变量组件打字稿:

...
@Input() data: any;
@Input() componentName: string;
...

通用变量组件.html:

<ng-container *ngIf="componentName === 'c1'"><component1 [data]="data"></component1></ng-container>
<!-- Repeat the above with whatever components you end up needing -->

component1.html: &lt;div&gt;Hi, I'm comp 1. Data: data&lt;/div&gt;

component2.html:&lt;div&gt;Hi, I'm comp 2. Variable component: &lt;generic-variable-component [data]="data" [componentName]="varCompName"&gt;&lt;/generic-variable-component&gt;&lt;/div&gt;

component2在某处的使用:&lt;component2 [varCompName]="c1" &gt;&lt;/component2&gt;

这似乎按我想要的方式工作。缺点是每次我添加一种我想在这种情况下使用的新类型的组件时,我都必须去编辑 generic-variable-component.html,但这真的没什么大不了的,你只需复制那行。可能有更好的方法来做到这一点,包括内容注入和指令,但我不知道该怎么做。

另外,我对在 *** 上发帖有点陌生,所以我不确定是否应该将我的问题标记为已回答,因为我的解决方法是。我想现在我会保留它,以防有人想用“正确”答案猛扑过来。

【问题讨论】:

【参考方案1】:

我认为您应该阅读有关content projection 的信息。它的作用是为您提供一种将您想要的任何内容作为参数传递给组件的方法。例如:

父组件

<component1>
    <componentAsAParameter></componentAsAParameter>
</component1>

在 component1 Html 中,您可以使用通过 ng-content 作为参数传递的组件

<div>
    whatever you want
    <ng-content></ng-content>
</div>

Html,在运行时看起来像:

<div>
    whatever you want
    <componentAsAParameter></componentAsAParameter>
</div>

【讨论】:

来自您的链接:“我们无法与 ng-content 标签交互,例如在其之上定义事件侦听器。”我需要将可变行数据传递给 ng-content,但看起来我做不到。 您可以添加 eventListiner,但必须在父级别完成。您可以使用 querySelector 或 ViewChild 与 ng-content 进行交互,例如:在显示 ng-content 后选择包含该元素的元素。我知道这是可能的,因为我做到了,但我不记得到底是怎么回事

以上是关于有没有办法在另一个组件中使用可变 Angular 组件,并将数据传递给该可变组件?的主要内容,如果未能解决你的问题,请参考以下文章

Angular7 - 在另一个组件中注入组件

Angular - 在另一个组件中动态注入一个组件

Angular 10 在另一个内部使用一个组件(错误:不是已知元素)

Angular 2:在另一个组件上定义路由器而不是引导组件

有没有办法在另一个 JSS 样式的组件中定位嵌套的 JSS 样式的组件? [JSS-nested/Styled-JSS/Material UI (React)]

如何在另一个模块/路由器中使用组件