Как обнаружить асинхронное изменение в 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);
      }
    }
    
Другие вопросы по тегам