Как обнаружить асинхронное изменение в ng-контенте
Я сделал компонент, который использует marked
пакет для рендеринга контента уценки, дело в том, что он не рендерится сам, когда асинхронное событие меняет свое ng-content
элемент.
Вот код
import {Component, ElementRef, AfterContentInit} from 'angular2/core';
declare var marked: any;
@Component({
selector: 'markdown',
template:
'<div style="display:none;">' +
' <ng-content></ng-content>' +
'</div>' +
'<div class="markdown" [innerHTML]="output"></div>'
})
export class MarkdownComponent implements AfterContentInit {
output: string;
constructor(
private element: ElementRef) {
}
ngAfterContentInit() {
const c = this.element.nativeElement.childNodes;
this.output = marked(c[0].textContent);
}
}
Вот фрагмент кода HTML:
<markdown>{{info}}</markdown>
А вот и асинхронное обновление:
updateInfo(text: string) {
this.svc.update(this.info, text).subscribe(
data => this.info = data.newText);
}
Проблема в том, когда this.svc.update
события пожары, info
переменная меняет значение, но markdown
Компонент не перерисовывается.
Спасибо!
РАЗРЕШАЮЩАЯ СПОСОБНОСТЬ
Следуя совету принятого ответа (спасибо Гюнтеру), вот новый компонент, он стал проще и проще:
import {Component} from 'angular2/core';
declare var marked: any;
@Component({
selector: 'markdown',
template: '<div class="markdown" [innerHTML]="process(md)"></div>',
inputs: ['md']
})
export class MarkdownComponent {
md: string;
process(s: string) {
if (!s) return '';
return marked(s);
}
}
А вот и новый HTML:
<markdown [md]="info"></markdown>
Работает отлично!:)
2 ответа
Добавление @Input() content;
и используя компонент, как
<markdown [content]="info"></markdown>
сделает это проще.
В качестве альтернативы MutationObserver должен хорошо работать для этого варианта использования.
Даже если ответ Гюнтера будет великим, я не смог удержаться, чтобы создать небольшой план, описывающий, как использовать Marked в компоненте: https://plnkr.co/edit/0oSeaIyMWoq5fAKKlJLA?p=preview.
Вот подробности:
Отмечена конфигурация HTML-файла
<script> System.config({ transpiler: 'typescript', typescriptOptions: { emitDecoratorMetadata: true }, packages: { 'src': {defaultExtension: 'ts'} }, map: { marked: 'https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.5/marked.js' } }); System.import('src/boot') .then(null, console.error.bind(console)); </script>
Компонент, который использует помеченные
import { Component, Input } from 'angular2/core'; import marked from 'marked'; @Component({ selector: 'markdown', template: ` <div [innerHTML]="convertedData"></div> ` }) export class MarkdownComponent { @Input('data') data:string; ngOnChanges() { this.convertedData = marked(this.data); } }
Компонент, который использует предыдущий компонент Markdown
import { Component } from 'angular2/core'; import { MarkdownComponent } from './markdown'; @Component({ selector: 'my-app', template: ` <div> <markdown [data]="markdown"></markdown> </div> `, directives: [ MarkdownComponent ] }) export class AppComponent { constructor() { this.markdown = 'Hello'; setTimeout(() => { this.markdown = ` # Title Some __test__ `; }, 1000); } }