Angular 6 - 将子组件渲染为父组件中的内容

Posted

技术标签:

【中文标题】Angular 6 - 将子组件渲染为父组件中的内容【英文标题】:Angular 6 - Render child component as content in parent component 【发布时间】:2019-04-09 05:49:36 【问题描述】:

我正在学习 Angular,但我面临的问题对于我的实际知识来说太难了。

我正在尝试使用 Material Angular CDK 构建仪表板。仪表板内的每张卡片都会呈现不同的图表。这是问题,我将组件作为内容传递的组件,它被呈现为字符串而不是组件(屏幕截图)。文件夹结构为:

应用程序根 标题 仪表板 图形类型 1 图形类型 2 ... 图形类型 n

您将在下面找到所有相关文件的代码。让我知道是否缺少某些东西。感谢谁会尽力帮助我:)


dashboard-rev3.component.html


<div class="grid-container">
      <mat-grid-list cols="12" rowHeight="350px">
        <mat-grid-tile *ngFor="let card of cards | async" [colspan]="card.cols" [rowspan]="card.rows">
          <mat-card class="dashboard-card">
            <mat-card-header>
              <mat-card-title>
                card.title
                <button mat-icon-button class="more-button" [matMenuTriggerFor]="menu" aria-label="Toggle menu">
                  <mat-icon>more_vert</mat-icon>
                </button>
                <mat-menu #menu="matMenu" xPosition="before">
                  <button mat-menu-item>Move</button>
                  <button mat-menu-item>Edit</button>
                  <button mat-menu-item>Delete</button>
                </mat-menu>
              </mat-card-title>
            </mat-card-header>
            <mat-card-content class="dashboard-card-content">
             card.content
            </mat-card-content>
          </mat-card>
        </mat-grid-tile>
      </mat-grid-list>
    </div>


----------


dashboard-rev3.component.ts



  import  Component  from '@angular/core';
    import  map  from 'rxjs/operators';
    import  Breakpoints, BreakpointObserver  from '@angular/cdk/layout';



    @Component(
      selector: 'app-dashboard-rev3',
      templateUrl: './dashboard-rev3.component.html',
      styleUrls: ['./dashboard-rev3.component.css'],
    )
    export class DashboardRev3Component 

      /** Based on the screen size, switch from standard to one column per row */
      cards = this.breakpointObserver.observe(Breakpoints.Handset).pipe(
        map(( matches ) => 
          if (matches) 
            return [
               title: 'Active Contracts', cols: 12, rows: 1, content: '<app-graph-bar></app-graph-bar>' ,
               title: 'Building Trends Bar Graph', cols: 12, rows: 1, content: '<app-graph-bar></app-graph-bar>' ,
               title: 'Rate Clock - Currency PPU', cols: 12, rows: 1, content: '<app-graph-bar></app-graph-bar>'  ,
               title: 'Building Trends Bar Graph', cols: 12, rows: 1, content: '<app-graph-bar></app-graph-bar>'  ,
               title: 'Hammersmith - consumption analysis - YoY Analysis', cols: 12, rows: 1, content: '<app-graph-trend></app-graph-trend>'  
            ];
          

          return [
             title: 'Active Contracts', cols: 5, rows: 1, content: '<app-graph-bar></app-graph-bar>'  ,
             title: 'Building Trends Bar Graph', cols: 7, rows: 1, content: '<app-graph-bar></app-graph-bar>'  ,
             title: 'Rate Clock - Currency PPU', cols: 4, rows: 1, content: '<app-graph-bar></app-graph-bar>'  ,
             title: 'Building Trends Bar Graph', cols: 8, rows: 1, content: '<app-graph-bar></app-graph-bar>'  ,
             title: 'Hammersmith - consumption analysis - YoY Analysis', cols: 12, rows: 1, content: '<app-graph-trend></app-graph-trend>' 

          ];
        )
      );

      constructor(private breakpointObserver: BreakpointObserver) 
    


----------

graph-bar.component.ts

import  Component, OnInit, Input  from '@angular/core';

@Component(
  selector: 'app-graph-bar',
  templateUrl: './graph-bar.component.html',
  styleUrls: ['./graph-bar.component.css']
)

export class GraphBarComponent implements OnInit 

  dataSource: Object;
  constructor() 
      this.dataSource = 
          "chart": 
              "caption": "Countries With Most Oil Reserves [2017-18]",
              "subCaption": "In MMbbl = One Million barrels",
              "xAxisName": "Country",
              "yAxisName": "Reserves (MMbbl)",
              "numberSuffix": "K",
              "theme": "fusion",

          ,
          // Chart Data
          "data": [
              "label": "Venezuela",
              "value": "290"
          , 
              "label": "Saudi",
              "value": "260"
          , 
              "label": "Canada",
              "value": "180"
          , 
              "label": "Iran",
              "value": "140"
          , 
              "label": "Russia",
              "value": "115"
          , 
              "label": "UAE",
              "value": "100"
          , 
              "label": "US",
              "value": "30"
          , 
              "label": "China",
              "value": "30"
          ]
      ; // end of this.dataSource
  ngOnInit() 
  


【问题讨论】:

问题不清楚,能否改写一下? 您是否尝试过将content 绑定到容器组件的[innerHTML] 属性? 这正是Dynamic Component Loader 的用途。 【参考方案1】:

在 Angular 中,文本内容和 HTML 内容在 DOM 模板中是不相等的。为了安全起见,内容会被清理,因此当您尝试将包含 HTML 标记作为字符串的内容插入到模板中时,它只是呈现为文本,而不是作为 DOM 插入。

通常,您会执行以下操作:

<mat-card-content class="dashboard-card-content">
     <app-graph-bar></app-graph-bar>
</mat-card-content>

在模板中插入另一个组件。

如果插入的组件接受内容,那么它可能是这样的:

<mat-card-content class="dashboard-card-content">
     <app-graph-bar>card.content</app-graph-bar>
</mat-card-content>

如果组件需要根据内容有所不同,则可以使用模板逻辑:

<mat-card-content class="dashboard-card-content">
     <app-graph-bar *ngIf="card.type == 'bar'">card.content</app-graph-bar>
     <app-graph-pie *ngIf="card.type == 'pie'">card.content</app-graph-pie>
</mat-card-content>

底线是你不能做你尝试过的事,但你很可能可以做你想做的事。

正如其他人在 cmets 中提到的,有时您可以将内容绑定到 innerHTML,但这并不总是产生预期的结果。如果您需要更高级的功能,您可以使用动态组件加载。

【讨论】:

谢谢大家,我将研究动态组件加载器,并尝试 G. Tranter 解释的解决方案。我会尽快更新你的:)

以上是关于Angular 6 - 将子组件渲染为父组件中的内容的主要内容,如果未能解决你的问题,请参考以下文章

有条件地将子组件导入到父模板 angular 5

将子组件添加到父组件并将父组件添加到文档

如何从 Angular 2 中的数据渲染静态 Angular 组件? [复制]

实体框架 6:将子对象添加到父列表与将子对象的导航属性设置为父对象

react——Portals:将子节点渲染到存在于父组件以外的 DOM 节点

如何将子组件转移到组件?