Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to get the HTML template for an Angular* component?

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 &gt;, < needs to be &lt;). 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('<', '&lt;').replace('>', '&gt;');
  }
}

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('<', '&lt;').replace('>', '&gt;'); 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?

like image 655
peinearydevelopment Avatar asked Aug 04 '17 02:08

peinearydevelopment


People also ask

How do I display Angular components in HTML?

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 .

Can I use HTML template in Angular?

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.

How do I access ng template in component?

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 .


1 Answers

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

  • When and how s decorator applied to the decorated classes from the @angular packages
  • Read and List all exports of an angular module

  • Example of how angular parses template

like image 135
yurzui Avatar answered Oct 06 '22 00:10

yurzui