将上下文传递给 Angular 2 组件的投影内容(使用 ng-content)

Posted

技术标签:

【中文标题】将上下文传递给 Angular 2 组件的投影内容(使用 ng-content)【英文标题】:Passing context to an Angular 2 component's projected content (using ng-content) 【发布时间】:2016-10-24 09:01:43 【问题描述】:

我正在编写一个可重用的 Angular 2 组件来检索和显示表格中的数据,以及服务器端排序、过滤和搜索。我希望表中的每一行都有一个额外的列,其中包含使用 ng-context 标记的通用 html,我可以做到这一点。

最常见的情况是有按钮可以使用构建每行的数据执行操作(例如,导航到条目的特定页面,或删除条目),但似乎没有是一种将对象传递给组件的 ContentChildren 的方法。我也许可以通过直接的 DOM 操作和检查来实现这一点,但这既非常笨拙,也不利于可重用性。

我并不真正关心实现这一点的任何具体方法,只要它:

允许我将通用 html 添加为组件的子组件 可以将一些通用数据从父组件传递到其 ContentChildren(前面提到的通用 html),以便子组件的事件处理程序可以使用这些数据。

我正在使用 typescript,因此首选类型安全的解决方案,但如果需要,我很乐意忽略类型系统。

我使用的表格组件(my-table)看起来像

<my-table /* some properties */>
    <button class="row-button" type="button" (click)="navigate(/* context */)">Navigate</button>
</my-table>

使用 ng-content 的模板如下:

// table html
<tr *ngFor="let row of rows">
    <td *ngFor="let column of row.columns">column</td>
    <td>
        <ng-content select=".row-button"></ng-content>
    </td>
</tr>
// more table html

如果我可以向 ng-content 传递一个参数,该参数可由按钮元素使用就足够了。

【问题讨论】:

如果您可以添加一些代码来显示您尝试完成的具体示例,这将有所帮助。 “上下文”是怎样的?它从何而来?它应该在哪里可用?如果 X 发生,什么确切的属性应该发生什么。 我添加了一些伪代码,尽管我对实现它的实际方式持矛盾态度。 “上下文”只是一个对象,它来自父级,并且可以在子级的模板中使用(或者我可以完成它) 什么是“父”? &lt;my-table&gt;是模板中包含第一个代码sn-p的父级还是组件。在后一种情况下,如果父级在组件类中有 content 属性,这应该可以工作。 将是通用组件,它是具有行/列集合的父组件。第一个示例中的按钮将被投影到其模板 html 内的 标记中。我会更新问题以使其更清楚。 【参考方案1】:

如果您对使用 ng-content 不严格,ng-template 可以完成这项工作:

<my-table [rowButtonTemplate]="buttonTemplate" /* some properties */>
    <ng-template #buttonTemplate let-column>
        <button class="row-button" type="button" (click)="navigate(column.context)">Navigate</button>
    </ng-template>
</my-table>

然后在表内:

// table ts
@Input()
rowButtonTemplate: TemplateRef;


// table html
<tr *ngFor="let row of rows">
    <td *ngFor="let column of row.columns">column</td>
    <td>
        <ng-container *ngTemplateOutlet="rowButtonTemplate; context:  $implicit: column, index: index "></ng-container>
    </td>
</tr>
// more table html

【讨论】:

这是唯一对我有用的东西。尝试:将项目内容转换为模板 |项目内容模板| ...(与 ViewChild、ContentChild、ngContainer、ngContent 的 X 组合)。疯狂的是,Angular 无法单独提供内容投影。【参考方案2】:

一种方法是使用允许您显式引用父级的模板变量:

<my-table #myTable>
  <button [context]="myTable.context">
</my-table>

据我所知,有计划使其更加灵活。我猜是这个问题https://github.com/angular/angular/issues/8563

【讨论】:

此解决方案不允许我传入每一行的数据。如果无法访问行上的循环的索引,我无法将正确的行传递给孩子。不过,我可以看到它会如何正常工作,我会密切关注这个问题。 我明白你的意思了。我以前没有看到。在*ngFor 中添加&lt;ng-content&gt; 无论如何都不起作用。一切都将被嵌入到带有匹配选择器的第一个 &lt;ng-content&gt; 标记中。 计划增加对这个用例的支持,但我不知道这可能需要多长时间才能落地。我认为这是要关注的问题github.com/angular/angular/issues/8563

以上是关于将上下文传递给 Angular 2 组件的投影内容(使用 ng-content)的主要内容,如果未能解决你的问题,请参考以下文章

通过Angular组件将函数作为参数传递给(单击)事件

如何将带参数的函数传递给Angular中的内部组件

通过 HOC 将 React 上下文传递给包装的组件

将未知上下文传递给子组件

如何使用 MatDialog 将行数据或数组对象传递给 Angular 中的组件

将路径参数传递给 React 上下文提供程序