获取 ng-content 的原始/原始模板值

Get the original / raw template value of ng-content

是否可以得到ng-content的预处理值? 我正在构建设计系统文档并希望在不重复的情况下显示示例代码

html:

<tr>
  <td #contentEl>
    <ng-content #projected></ng-content>
  </td>
  <td>
    <mat-icon (click)="copyTagToClipboard()">content_paste</mat-icon>
  </td>
  <td>
    <pre>{{ contentEl.innerHTML }}</pre>
  </td>
</tr>

打字稿

export class CodeExampleComponent implements OnInit, AfterContentInit {
  @ViewChild('contentEl') contentEl: HTMLTableCellElement;
  @ContentChild('template') template;
  @ViewChild('projected', { read: TemplateRef, static: true }) content;

  constructor() {}

  ngOnInit() {
    console.log(this.content);
  }

  ngAfterContentInit(): void {
    console.log(this.template);
  }
  
  copyTagToClipboard() {
    if (!this.contentEl) return;
    copyToClipboard(this.contentEl.innerHTML);
  }
}

用法:

  <app-code-example>
    <template #template><app-footnote>Footnote</app-footnote></template>
  </app-code-example>

我所能得到的只是 ng-content/template 的 angular 渲染内容,而不是原始原始模板。

这不一定能回答您有关从 ng-content 获取预处理 HTML 的问题。但是,这种方法可用于解决有关显示 HTML 作为示例的问题。您可以将原始 html 作为字符串导入并将其用作变量。然后我喜欢做的是创建一个或多个组件来演示我正在记录的某些组件的用法。

这有点多,所以我把它们都放在一个 StackBlitz 中来尝试演示。

src 目录中创建一个名为 typings.d.ts 的文件,允许我们将 html 文件作为文本导入。

declare module "*.html" {
  const content: string;
  export default content;
}

创建我们所有示例组件都需要实现的抽象class。我们需要它是抽象的,因为我们稍后将使用 QueryList

export abstract class Example {
  templateText: string; //the raw html to display 
}

创建一个示例包装器组件,显示实时示例、原始 html 并具有您的复制按钮

import { Component, ContentChildren, Input, QueryList } from "@angular/core";
import { Example } from "../example";

@Component({
  selector: "app-example",
  template: `
    <div class="wrapper">
        <h1>{{label}}</h1>
        <ng-content></ng-content>
    
        <br />
        <button (click)="copyTagToClipboard()">Copy Content</button>
    
        <div>
            <pre>{{ example.templateText }}</pre>
        </div>
    </div>
  `
})
export class ExampleComponent{
  @Input() label: string; 
  
  @ContentChildren(Example) items: QueryList<Example>;
  example: Example;

  ngAfterContentInit(): void {
    //grab the first thing that implements the "Example" interface
    //hypothetically this component could be re-worked to display multiple examples!
    this.example = this.items.toArray()[0];    
  }

  copyTagToClipboard() {
    alert(this.example.templateText);
  }
}

构建一个组件,演示如何使用您正在记录的任何组件。请注意我们如何将 html 文件作为变量导入并将其用作组件的属性,以满足接口。不要忘记设置提供程序,以便 QueryList 可以使用该组件。然后,您可以根据需要构建任意数量的此类示例,也许每个用例构建一个不同的组件。

import { Component, TemplateRef, ViewChild } from "@angular/core";
import { Example } from "../example";

// See typings.d.ts, which sets up the module that allows us to do this
import * as template from "./my-component-example.component.html";
// or const template = `<app-my-component [label]="myLabelValue"></app-my-component>`;

@Component({
  selector: "app-my-component-example",
  template,
  styleUrls: ["./my-component-example.component.css"],

  //this is so the QueryList works in the example wrapper
  providers: [{ provide: Example, useExisting: MyComponentExampleComponent }]
})
export class MyComponentExampleComponent implements Example {
  myLabelValue = "Test Label!!";
  templateText = template.default;
}

最后,把它们放在一起

<app-example label="Basic Example">
  <app-my-component-example></app-my-component-example>
</app-example>

我觉得通过这种方法,您可以灵活地创建每个示例。