I'm trying to create a library of shared Angular components to use across a number of different web projects. Along with the shared component library, I'm trying to create a web project that contains and displays all of those components and code examples as to how to use them.
As seen from other queries related to a similar question, in order to display HTML code in a webpage in in <pre>
or <code>
tags, certain aspects of those HTML snippets need to have HTML encoded characters(i.e. >
needs to be >
, <
needs to be <
). The need to make these changes by hand from the source code can be quite onerous and tedious.
I would like to find a way to be able to read the HTML template for a given component, make the few text replacements needed and then set that value to a property to be displayed in the view. I've seen other similar SO questions that have a different and insufficient answer such as this.
If I have foo.component.ts
as follows:
import { Component } from '@angular/core';
@Component({
selector: 'foo',
template: `
<div class="foo">
<div class="content">
<ng-content select="[top-content]"></ng-content>
</div>
<div class="extra content">
<ng-content select="[bottom-content]"></ng-content>
</div>
</div>
`
})
export class FooComponent {}
I want to create a display-foo.component.ts
with something as follows:
import { Component } from '@angular/core';
import { FooComponent } from './foo.component';
@Component({
selector: 'display-foo',
template: `
<pre class="example-code">
<code>
{{encodedExampleHtml}}
</code>
</pre>
<foo>
<div top-content>TOP</div>
<div bottom-content>BOTTOM</div>
</foo>
`
})
export class DisplayFooComponent {
encodedExampleHtml: string;
constructor() {
this.encodedExampleHtml = new FooComponent().template.replace('<', '<').replace('>', '>');
}
}
In essence this would put the template in the UI for the next developer to see and understand how to utilize as well as an actual rendered element of that type of component as well displaying what the component would look like when used in an actual application.
The part of the DisplayFooComponent
that I can't figure out how to work is this line this.encodedExampleHtml = new FooComponent().template.replace('<', '<').replace('>', '>');
Take that as pseudocode for what I would like to do because an Angular component object has no template property and as far as I can see no property that exposes the template for that component.
Is there a way to utilize the Angular framework to get the HTML template for a component? Again I don't want the interpolated content with expressions replaced, but the actual raw HTML template that is associated with an element either by the decorator's template
property or its templateUrl
property?
The easiest way to display a component property is to bind the property name through interpolation. With interpolation, you put the property name in the view template, enclosed in double curly braces: {{myHero}} . Use the CLI command ng new displaying-data to create a workspace and app named displaying-data .
An Angular HTML template renders a view, or user interface, in the browser, just like regular HTML, but with a lot more functionality. When you generate an Angular application with the Angular CLI, the app. component. html file is the default template containing placeholder HTML.
To access the above ng-template in the component or directive, first, we need to assign a template reference variable. #sayHelloTemplate is that variable in the code below. Now, we can use the ViewChild query to inject the sayHelloTemplate into our component as an instance of the class TemplateRef .
You can try using special function to get annotations:
annotation.ts
declare let Reflect: any;
export function getAnnotation(typeOrFunc: Type<any>): any[]|null {
// Prefer the direct API.
if ((<any>typeOrFunc).annotations) {
let annotations = (<any>typeOrFunc).annotations;
if (typeof annotations === 'function' && annotations.annotations) {
annotations = annotations.annotations;
}
return annotations[0];
}
// API of tsickle for lowering decorators to properties on the class.
if ((<any>typeOrFunc).decorators) {
return convertTsickleDecoratorIntoMetadata((<any>typeOrFunc).decorators)[0];
}
// API for metadata created by invoking the decorators.
if (Reflect && Reflect.getOwnMetadata) {
return Reflect.getOwnMetadata('annotations', typeOrFunc)[0];
}
return null;
}
function convertTsickleDecoratorIntoMetadata(decoratorInvocations: any[]): any[] {
if (!decoratorInvocations) {
return [];
}
return decoratorInvocations.map(decoratorInvocation => {
const decoratorType = decoratorInvocation.type;
const annotationCls = decoratorType.annotationCls;
const annotationArgs = decoratorInvocation.args ? decoratorInvocation.args : [];
return new annotationCls(...annotationArgs);
});
}
and then
this.encodedExampleHtml = getAnnotation(FooComponent).template;
Plunker Example
See also
Read and List all exports of an angular module
Example of how angular parses template
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With