Angular 6 - рендеринг дочернего компонента как содержимого в родительском компоненте - PullRequest
0 голосов
/ 05 ноября 2018

Я изучаю Angular и сталкиваюсь с проблемой, слишком сложной для моих реальных знаний.

Я пытаюсь создать панель инструментов, используя Material Angular CDK. Каждая карта внутри панели будет отображать другой график. Здесь проблема, компонент, который я передаю компоненту как контент, и он отображается как строка, а не как компонент (скриншот). Структура папок:

  • приложение-корень
    • Заголовок
    • Приборная панель
      • GraphType 1
      • GraphType 2
      • ...
      • GraphType n

Ниже вы найдете код для всех задействованных файлов. Дайте мне знать, если чего-то не хватает. Спасибо, кто попытается мне помочь:)

enter image description here


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() {
  }

}

1 Ответ

0 голосов
/ 05 ноября 2018

В 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, но это не всегда дает желаемый результат. А если вам нужны более продвинутые возможности, вы можете использовать динамическую загрузку компонентов.

...