#angular #ng-content
#angular #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>
typescript
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, а не исходный необработанный шаблон.
Ответ №1:
Это не обязательно отвечает на ваш вопрос о получении предварительно обработанного HTML ng-content
. Однако этот подход может быть использован для решения вашей проблемы с отображением HTML-кода в качестве примера. Вы можете импортировать исходный HTML-код в виде строки и использовать его в качестве переменной. Что мне нравится делать, так это создавать компонент или несколько компонентов, которые демонстрируют использование какого-либо компонента, который я документирую.
Это довольно много, поэтому я поместил все это в StackBlitz, чтобы попытаться продемонстрировать.
Создайте файл прямо в src
названном каталоге typings.d.ts
, который позволяет нам импортировать html-файлы в виде текста.
declare module "*.html" {
const content: string;
export default content;
}
Создайте абстрактный класс, который должен реализовать весь наш примерный компонент. Нам нужно, чтобы оно было абстрактным, потому что мы собираемся использовать 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.defau<
}
Наконец, соберите все это вместе
<app-example label="Basic Example">
<app-my-component-example></app-my-component-example>
</app-example>
Я чувствую, что при таком подходе у вас есть большая гибкость при создании каждого примера.
Комментарии:
1. Это гениально. Стоит отметить, что для краткости мы могли бы поместить
my-component-example.component.html
в постоянную строку.