I'm quite new to Angular and I struggle with following problem.
I'd like to render the content of my component templates within the DOM. The goal is to produce a styleguide where I want to show code-snippets of the templates. Therefor I need the escaped template-content.
I've tried several things and came up with a possible solution to create a custom renderer which escapes the template output.
I thought it could be as easy as described here: Rendering in Angular But... it wasn't.
I created as described here Stack Overflow - custom-renderer-for-angular2 a custom renderer, which should first of all function like the default DebugDomRenderer. But I do not know how to use this renderer.
I tried things like:
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{
}
This part is not ready yet. My plan is to take the ChildViews and render them escaped...
My EscapeRootRender does exactly the same thing as the DebugDomRootRenderer except that I removed the debug stuff and added some 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); }
}
Now to the question(s):
- Is that (customRenderer) a way to handle the problem of escaping template-content, or am I totally wrong?
- How can I tell a single component to use a different Renderer?
Thanks for some help,
best Jan