如何检测ng-content

时间:2016-02-01 18:40:03

标签: angular

我创建了一个使用marked包来呈现markdown内容的组件,当异步事件更改其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组件不会重新呈现。

谢谢!

解决

按照接受的答案的建议(感谢Gunter),这是新组件,它更精简,更简单:

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 个答案:

答案 0 :(得分:3)

添加@Input() content;并使用

等组件
<markdown [content]="info"></markdown>

会让这更容易。

或者,MutationObserver适用于此用例。

答案 1 :(得分:2)

即使Günter的答案很好,我也无法抗拒创建一个描述如何将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);
      }
    }