Angular 6 - 将子组件渲染为父组件中的内容
Angular 6 - Render child component as content in parent component
我正在学习 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() {
}
}
在 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>
最重要的是,你不能做你已经尝试过的事,但你很可能可以做你想做的事。
正如其他人在评论中提到的,有时您可以将内容绑定到 innerHTML
,但这并不总能产生预期的结果。如果您需要更高级的功能,您可以使用动态组件加载。
我正在学习 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() {
}
}
在 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>
最重要的是,你不能做你已经尝试过的事,但你很可能可以做你想做的事。
正如其他人在评论中提到的,有时您可以将内容绑定到 innerHTML
,但这并不总能产生预期的结果。如果您需要更高级的功能,您可以使用动态组件加载。