2017-08-04 94 views
1

我正在嘗試創建一個共享Angular組件的庫,以便用於多個不同的Web項目。隨着共享組件庫,我試圖創建一個Web項目,其中包含並顯示所有這些組件和代碼示例以瞭解如何使用它們。有沒有辦法獲取Angular *組件的HTML模板?

如從有關的類似問題的其他查詢看出,爲了在網頁中在<pre><code>標籤顯示HTML代碼,這些HTML片段的某些方面需要有HTML編碼的字符(即>需要是&gt;<需要是&lt;)。手動從源代碼進行這些更改的需求可能非常繁瑣和繁瑣。

我想找到一種方法來讀取給定組件的HTML模板,使少量文本替換所需,然後將該值設置爲要顯示在視圖中的屬性。我見過其他類似的SO問題,如this

如果我有foo.component.ts如下:

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 {} 

我想創建一個display-foo.component.ts的東西如下:

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;'); 
    } 
} 

在本質上,這將使該模板在UI下一個開發商查看並理解如何利用以及該類型組件的實際渲染元素以及顯示組件在實際應用程序中使用時的外觀。

DisplayFooComponent我無法弄清楚如何工作的部分是這一行this.encodedExampleHtml = new FooComponent().template.replace('<', '&lt;').replace('>', '&gt;');把它當作我想做的事情的僞代碼,因爲Angular組件對象沒有模板屬性,而且據我所見沒有顯示該組件的模板的屬性。

有沒有一種方法可以利用Angular框架獲取組件的HTML模板?同樣,我不希望帶有表達式的內插內容被替換,而是由裝飾器的template屬性或其templateUrl屬性與元素相關聯的實際原始HTML模板?

+0

你打算使用AOT嗎? – yurzui

+0

@yurzui是的,我正在計劃它 – peinearydevelopment

回答

3

您可以嘗試使用特殊功能來獲得註釋:

註解。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); 
    }); 
} 

然後

this.encodedExampleHtml = getAnnotation(FooComponent).template; 

Plunker Example

參見

+0

啊,熟悉的事情) –

+0

@Maximus是啊,你是。這裏沒有新東西。這是基本的水平 – yurzui

+0

這似乎不是角度特定的,而是從任何裝飾者獲取任何信息的方式。有沒有任何角度特定的機制? – peinearydevelopment

0

yurzui's answer工作正常角4.4.2而不是5.0.2。註釋機制已更改:使用屬性而不是Reflect.defineMetadata()來存儲元數據。因爲它沒有記錄,人們只能在代碼中找到它:

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

@angular/core/@angular/core.js,l.356),以

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; 
}); 
在角5.0.2

@angular/core/esm2015/core.js,L 0.96)。

訪問元數據的更新代碼,例如模板:

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); 
    }); 
} 
相關問題