如何在Angular2中使用自定义渲染器

时间:2016-09-16 09:59:07

标签: angularjs angular

我对Angular很新,我在解决以下问题时很困难。

我想在DOM中呈现我的组件模板的内容。我的目标是制作一个样式指南,我想在其中显示模板的代码片段。因此,我需要转义模板内容。

我尝试了几件事,并想出了一个可能的解决方案来创建一个逃脱模板输出的自定义渲染器。

我认为它可以像在此描述的那样简单:Rendering in Angular 但是......它不是。

我按照Stack Overflow - custom-renderer-for-angular2这里描述的方式创建了一个自定义渲染器,它首先应该像默认的DebugDomRenderer一样运行。但我不知道如何使用这个渲染器。

我尝试过这样的事情:

import {Component} from '@angular/core';
import {EscapeRootRenderer} from "../../renderer/escapeRootRenderer";
import {DebugDomRootRenderer} from "@angular/core/src/debug/debug_renderer";

@Component({
  selector:'escape',
  template:'<pre><code><ng-content></ng-content></code></pre>',
  providers:[
    {provide: DebugDomRootRenderer, useClass:EscapeRootRenderer}
  ]
})

export class EscapeComponent{

}

此部分尚未准备好。我的计划是使用ChildViews并将它们渲染出来......

我的EscapeRootRender与DebugDomRootRenderer完全相同,只是我删除了调试内容并添加了一些console.logs()

import {Injectable, RenderComponentType, Renderer, RootRenderer} from '@angular/core';

import {AnimationStyles} from "@angular/core/esm/src/animation/animation_styles";
import {AnimationKeyframe} from "@angular/core/esm/src/animation/animation_keyframe";


@Injectable()
export class EscapeRootRenderer implements RootRenderer {

  constructor(private _delegate:RootRenderer) {
    console.log('EscapeRootRenderer constructed')
    console.log(_delegate)
  }


  renderComponent(componentProto: RenderComponentType): EscapeRenderer {
    console.log('EscapeRootRenderer - renderComponent');
    return new EscapeRenderer(this._delegate.renderComponent(componentProto));
  }

}

export class EscapeRenderer implements Renderer{

  constructor(  private _delegate: Renderer){
    console.log('EscapeRenderer constructed');
  }

  animate(element: any, startingStyles: AnimationStyles, keyframes: AnimationKeyframe[], duration: number, delay: number, easing: string): any {
    console.log('EscapeRenderer animate');
    return this._delegate.animate(element, startingStyles, keyframes, duration, delay, easing);
  }

  selectRootElement(selector: string): any {
    console.log('EscapeRenderer selectRootElement');
    var nativeEl = this._delegate.selectRootElement(selector);
    return nativeEl;
  }

  createElement(parentElement: any, name: string): any {
    console.log('EscapeRenderer createElement');
    var nativeEl = this._delegate.createElement(parentElement, name);
    return nativeEl;
  }

  createViewRoot(hostElement: any): any {
    console.log('EscapeRenderer createViewRoot');
    return this._delegate.createViewRoot(hostElement); }

  createTemplateAnchor(parentElement: any): any {
    console.log('EscapeRenderer createTemplateAnchor');
    var comment = this._delegate.createTemplateAnchor(parentElement);
    return comment;
  }

  createText(parentElement: any, value: string): any {
    console.log('EscapeRenderer createText');
    var text = this._delegate.createText(parentElement, value);
    return text;
  }

  projectNodes(parentElement: any, nodes: any[]) {
    console.log('EscapeRenderer projectNodes');
    return this._delegate.projectNodes(parentElement, nodes);
  }

  attachViewAfter(node: any, viewRootNodes: any[]) {
    console.log('EscapeRenderer attachViewAfter');
    return this._delegate.attachViewAfter(node, viewRootNodes);
  }

  detachView(viewRootNodes: any[]) {
    console.log('EscapeRenderer detachView');
    return this._delegate.detachView(viewRootNodes);
  }

  destroyView(hostElement: any, viewAllNodes: any[]) {
    console.log('EscapeRenderer destroyView');
    return this._delegate.destroyView(hostElement, viewAllNodes);
  }

  listen(renderElement: any, name: string, callback: Function) {
    console.log('EscapeRenderer listen');
    return this._delegate.listen(renderElement, name, callback);
  }

  listenGlobal(target: string, name: string, callback: Function): Function {
    console.log('EscapeRenderer listenGlobal');
    return this._delegate.listenGlobal(target, name, callback);
  }

  setElementProperty(renderElement: any, propertyName: string, propertyValue: any) {
    console.log('EscapeRenderer setElementProperty');
    return this._delegate.setElementProperty(renderElement, propertyName, propertyValue);
  }

  setElementAttribute(renderElement: any, attributeName: string, attributeValue: string) {
    console.log('EscapeRenderer setElementAttribute');
    return this._delegate.setElementAttribute(renderElement, attributeName, attributeValue);
  }

  /**
   * Used only in debug mode to serialize property changes to comment nodes,
   * such as <template> placeholders.
   */
  setBindingDebugInfo(renderElement: any, propertyName: string, propertyValue: string) {
    console.log('EscapeRenderer setBindingDebugInfo');
    return this._delegate.setBindingDebugInfo(renderElement, propertyName, propertyValue);
  }


  setElementClass(renderElement: any, className: string, isAdd: boolean) {
    console.log('EscapeRenderer setElementClass');
    return this._delegate.setElementClass(renderElement, className, isAdd);
  }

  setElementStyle(renderElement: any, styleName: string, styleValue: string) {
    console.log('EscapeRenderer setElementStyle');
    return this._delegate.setElementStyle(renderElement, styleName, styleValue);
  }

  invokeElementMethod(renderElement: any, methodName: string, args: any[]) {
    console.log('EscapeRenderer invokeElementMethod');
    return this._delegate.invokeElementMethod(renderElement, methodName, args);
  }

  setText(renderNode: any, text: string) {
    console.log('EscapeRenderer setText');
    return this._delegate.setText(renderNode, text); }

}

现在问题:

  1. 那是(customRenderer)一种处理转义模板内容问题的方法,还是我完全错了?
  2. 如何判断单个组件使用不同的渲染器?
  3. 感谢您的帮助,

    最好的Jan

2 个答案:

答案 0 :(得分:2)

我在没有任何自定义渲染器的情况下解决了我的问题:

import {
  Component, ViewChild, OnInit, AfterViewInit, OnInit
} from '@angular/core';


@Component({
  selector:'escape',
  template:'<content #kiddo><ng-content></ng-content></content><pre><code #codeContent>{{componentInnerHTML}}</code></pre>'
})

export class EscapeComponent implements OnInit, AfterViewInit{
  @ViewChild('kiddo') viewChild;
  @ViewChild('codeContent') codeContent;
  componentInnerHTML:string;

  ngAfterViewInit(){
    this.componentInnerHTML = this.viewChild.nativeElement.innerHTML;
  }

  ngOnInit(){
    var that = this;
    setTimeout(()=>hljs.highlightBlock(that.codeContent.nativeElement), 1)
  }
}

结果现在看起来像这样。开发人员现在可以直接从网站上复制代码......

Screenshot output EscapeComponent

但是,我仍然对如何使用自定义渲染器感兴趣。

答案 1 :(得分:0)

我仍然不能完全理解这个问题,但也许这就是你想做的事情

<pre ngNonBindable>
    template content here
</pre>