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

允我心安 提交于 2019-11-29 04:54:45

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

yurzui's answer works fine for Angular 4.4.2 but not for 5.0.2. The annotation mechanism changed: a property instead of Reflect.defineMetadata() is used to store metadata. Since it's not documented, one can only find it in the code:

const /** @type {?} */ TypeDecorator = (function TypeDecorator(cls) {
    const /** @type {?} */ annotations = Reflect.getOwnMetadata('annotations', cls) || [];
    annotations.push(annotationInstance);
    Reflect.defineMetadata('annotations', annotations, cls);
    return cls;
});

in Angular 4.4.2 (@angular/core/@angular/core.js, l.356) to

const ANNOTATIONS = '__annotations__';
const /** @type {?} */ TypeDecorator = /** @type {?} */ (function TypeDecorator(cls) {
    // Use of Object.defineProperty is important since it creates non-enumerable property which
    // prevents the property is copied during subclassing.
    const /** @type {?} */ annotations = cls.hasOwnProperty(ANNOTATIONS) ?
        (/** @type {?} */ (cls))[ANNOTATIONS] :
        Object.defineProperty(cls, ANNOTATIONS, { value: [] })[ANNOTATIONS];
    annotations.push(annotationInstance);
    return cls;
});

in Angular 5.0.2 (@angular/core/esm2015/core.js, l.96).

Updated code for accessing Metadata, e.g. the template:

import 'reflect-metadata';

export function getAnnotation(typeOrFunc: Type<any>): any[]|null {
  // Prefer the direct API.
  if ((<any>typeOrFunc)['__annotations__']) {
      return (<any>typeOrFunc)['__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);
  });
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!