2017-08-04 2 views
1

Ich versuche, eine Bibliothek von geteilten Angular-Komponenten für eine Reihe von verschiedenen Web-Projekten zu erstellen. Zusammen mit der Bibliothek für gemeinsam genutzte Komponenten versuche ich ein Webprojekt zu erstellen, das all diese Komponenten und Codebeispiele enthält und anzeigt, wie sie verwendet werden.Gibt es eine Möglichkeit, die HTML-Vorlage für eine Angular * -Komponente zu erhalten?

Wie auf eine ähnliche Frage im Zusammenhang von anderen Abfragen zu sehen ist, um in müssen in <pre> oder <code> Tags, bestimmte Aspekte dieser HTML-Schnipsel in einer Webseite HTML-Code angezeigt werden HTML-codierte Zeichen haben (dh >&gt; sein muss , < muss &lt; sein). Die Notwendigkeit, diese Änderungen manuell vom Quellcode aus vorzunehmen, kann ziemlich beschwerlich und mühsam sein.

Ich möchte einen Weg finden, in der Lage zu sein, die HTML-Vorlage für eine bestimmte Komponente zu lesen, die wenigen erforderlichen Text-Ersetzungen vorzunehmen und diesen Wert dann auf eine Eigenschaft festzulegen, die in der Ansicht angezeigt werden soll. Ich habe andere ähnliche SO-Fragen gesehen, die eine andere und unzureichende Antwort haben, wie this.

Wenn ich foo.component.ts wie folgt:

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

ich ein display-foo.component.ts mit etwas schaffen wollen, wie folgt:

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

Im Wesentlichen würde dies die Vorlage in der Benutzeroberfläche für die nächste Entwickler setzen um zu sehen und zu verstehen, wie man ein tatsächlich wiedergegebenes Element dieses Komponententyps verwendet und wie die Komponente aussehen würde, wenn sie in einer tatsächlichen Anwendung verwendet wird.

Der Teil der DisplayFooComponent, die ich kann nicht herausfinden, wie zu arbeiten, ist diese Linie this.encodedExampleHtml = new FooComponent().template.replace('<', '&lt;').replace('>', '&gt;'); Nehmen Sie das als Pseudo-Code für das, was Ich mag tun würde, weil ein Angular Komponente Objekt keine Vorlage Eigenschaft hat und soweit ich sehen kann, Keine Eigenschaft, die die Vorlage für diese Komponente verfügbar macht.

Gibt es eine Möglichkeit, das Angular-Framework zu verwenden, um die HTML-Vorlage für eine Komponente zu erhalten? Erneut möchte ich nicht den interpolierten Inhalt mit Ausdrücken ersetzen, sondern die eigentliche Raw-HTML-Vorlage, die einem Element entweder durch die template -Eigenschaft des Dekorators oder seine templateUrl -Eigenschaft zugeordnet ist?

+0

Verwenden Sie AOT? – yurzui

+0

@ yurzui Ja, ich habe es auf – peinearydevelopment

Antwort

3

können Sie versuchen, spezielle Funktion Anmerkungen zu bekommen:

Anmerkung.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); 
    }); 
} 

und dann

this.encodedExampleHtml = getAnnotation(FooComponent).template; 

Plunker Example

Siehe auch

+0

ah, vertraute Sache geplant) –

+0

@Maximus ja, du bist. Nichts Neues hier. Es ist Grundstufe – yurzui

+0

Dies scheint nicht Angular spezifisch zu sein, aber eher eine Möglichkeit, um Informationen von jedem Dekorateur zu bekommen. Gibt es einen angularspezifischen Mechanismus? – peinearydevelopment

0

yurzui's answer arbeitet für Angular 4.4.2 in Ordnung, aber nicht für 5.0.2. Der Annotationsmechanismus wurde geändert: Eine Eigenschaft anstelle von Reflect.defineMetadata() wird zum Speichern von Metadaten verwendet. Da es nicht dokumentiert ist, kann man nur im Code finden:

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) zu

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).

Aktualisierter Code für den Zugriff auf Metadaten, z. die Vorlage:

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); 
    }); 
} 
Verwandte Themen