2016-03-24 13 views
2

Heute versuche ich meine eigene Anmerkung zu machen, um es in Angular2 Projekt zu verwenden. Diese Annotation muss eine Body-Klasse für eine bestimmte Komponente hinzufügen.Eigene Angular2 Annotation schreiben

Also, ich habe auf Angular Quellcode suchen, aber es ist so schwer zu sehen, wo und wie Annotation erstellt wurde.

Im Moment habe ich das versucht:

export function BodyClass(classes: any): ClassDecorator{ 
    classes = classes || {}; 

    if(typeof classes === 'string'){ 
     classes = {classes}; 
    } 

    return function changeBodyClass(){ 
     console.log('ici'); 
    } 
} 

Und meine Komponente:

import {Component} from "angular2/core"; 
import {RouterOutlet} from "angular2/router"; 
import {BodyClass} from "../core/annotations/body_class"; 

@Component({ 
    selector: 'my-component', 
    template: ` 
     <router-outlet></router-outlet> 
    `, 
}) 
@BodyClass('test') 
export class MyComponent{ 
} 

Meine Konsolenprotokoll in der Anmerkung korrekt gefeuert wurde, aber ich will "DOM" verwenden, Klasse von angular2/src/platform/dom/dom_adapter, um meine Klassen hinzuzufügen, aber DOM in undefined, wenn auf der Konsole log es (nicht zu instanziieren).

Die DOM-Klasse funktioniert jedoch direkt in meiner Komponente. Ich füge Klassen in ngOnInit Funktion hinzu und entferne sie auf ngOnDestroy.

Aber ich möchte dieses Verhalten auf vielen Komponenten, und ich denke, eine neue Anmerkung ist der beste Weg.

Vielleicht haben Sie eine bessere Idee dafür? Oder um mit der DOM-Klasse an einer Anmerkung zu arbeiten?

Danke!

Antwort

0

Es ist nicht so offensichtlich, da Sie auf der Komponenteninstanzebene und nicht auf der Komponentenklasse eins arbeiten möchten. Sie müssen also die entsprechende Konstruktorfunktion umbrechen.

export function MyComponentDecorator(value: string) { 
    return function (target: Function) { 
    var original = target; 

    function construct(constructor, args) { 
     var c : any = function() { 
     // Call the target constructor 
     var ret = constructor.apply(this, args); 

     // Add your additional processing 

     return ret; 
     } 
     c.prototype = constructor.prototype; 
     return new c(); 
    } 

    // The new constructor 
    // Don't forget to add a name at this function 
    // since Angular requires it for the template compilation 
    var f : any = function WrappedComponent(...args) { 
     return construct(original, args); 
    } 

    f.prototype = original.prototype; 

    return f; 
    } 
} 

An dieser Stelle umbrechen Sie die Komponenteninstanz, aber Sie verlieren die Komponentenmetadaten. Sie müssen sie von Hand kopieren:

f.prototype = original.prototype; 

var annotations = Reflect.getMetadata('annotations', original)); 
Reflect.defineMetadata('annotations', annotations, f); 

var properties = Reflect.getMetadata('propMetadata', original)); 
Reflect.defineMetadata('propMetadata', properties, f); 

return f; 

diesen Dekorateur verwenden einfach hinzufügen, bevor oder nachdem die @Component ein:

@MyComponentDecorator() 
@Component({ 
    selector: 'sub', 
    template: ` 
    <div (click)="showMessage()">Test</div> 
    ` 
}) 
export class SubComponent { 
    (...) 
} 

können Sie feststellen, dass dieser Dekorateur kopiert nur die Metadaten auf der Komponentenebene und nicht die anderen wie Eigenschaften (mit @Input) ...

Siehe diese Plunkr: https://plnkr.co/edit/PrAvliIpWTNFAtH33bHA?p=preview.

+0

Hmm danke Thierry. Ich werde deinen Plunkr mit deiner Erklärung überprüfen, und ich werde zurück sein;) – PallMallShow

Verwandte Themen