2016-05-17 3 views
3

Richtlinien in Angular2 haben keine "Scopes", während Komponenten tun. Aber in meinem Fall brauche ich die Richtlinie, um einen Anwendungsbereich zu schaffen. Sehen Sie sich meine App-Komponente an - sie hat eine HTML-Vorlage, und ANYWHERE für jedes Element könnte die foo-Direktive erscheinen. Dies sollte ein Datum aus dem Dienst holen und es dem Element zuweisen.Angular2 Direktive mit Scope

In Angular1 war es sehr einfach ... Richtlinien könnten ihren eigenen Umfang haben. Aber in Angular 2 finde ich keinen (auch nur schmutzigen) Weg, um das zu erreichen.

Es sieht wie eine einfache Aufgabe aus, nicht wahr?

@Directive({ 
    selector: '[foo]' 
}) 
class FooDirective { 
    @Input() 
    public id:string; 

    public bar; 

    constructor() { 
    this.bar = 'This is the "bar" I actually need. It is taken from DB let's say..' + this.id; 
    } 
} 




@Component({ 
    selector: 'app', 
    template: ` 
    <div foo id="2"> 
     This is random content 1: {{bar}} 
    </div> 

    <div foo id="2"> 
     This is random content 2: {{bar}} 
    </div> 
    `, 
    directives: [FooDirective] 
}) 
class App { 
    bar:string = 'This should be ignored, I need "bar" to be set from directive!'; 
} 

bootstrap(App); 

Antwort

5

Sie könnten versuchen, so etwas wie, dass eine lokale Variable nutzen, die die angelegte Richtlinie verweisen würde:

@Component({ 
    selector: 'app' 
    template: ` 
    <div foo id="2" #dir1="foo"> 
     This is random content 1: {{dir1.bar}} 
    </div> 

    <div foo id="2" #dir2="foo"> 
     This is random content 2: {{dir2.bar}} 
    </div> 
    `, 
    directives: [FooDirective] 
}) 
class App { 
    bar:string = 'This should be ignored, I need "bar" to be set from directive!'; 
} 

In Ihrem Fall bar ausgewertet wird anhand der Eigenschaften der aktuellen Komponente, die App ein.

bearbeiten (im Anschluss an die Bemerkung des @ yurzui)

Sie benötigen ein exportAs Eigenschaft in Ihrer Richtlinie hinzuzufügen:

@Directive({ 
    selector: '[foo]', 
    exportAs: 'foo' 
}) 
class FooDirective { 
    (...) 
} 
+0

Ja, das weiß ich. Aber lassen Sie uns sagen, dass ich eine "Helfer" -Richtlinie für unsere Designer erstelle, und ich sagte ihnen, "fügen Sie foo auf jedes Element hinzu, und es wird einige Daten aus der Datenbank holen" .. Und ich muss nicht "extra Arbeit" hinzufügen sie .. (Ich habe bereits dieses Tool mit eckigen 1, so dass sie nicht mein neues Werkzeug mit "mehr Arbeit für sie" mögen –

+1

Vergessen Sie nicht, exportAs hinzuzufügen: 'foo' innerhalb der Metadaten-Richtlinie. – yurzui

+0

Auch ich denke, dass es limit in einer Vorlage für diese "lokalen Variablen". Aber unsere Vorlagen sind ziemlich groß –

0

Was meinen, wenn Sie sagen, dass die Komponenten Umfang haben?

Mein Verständnis ist, dass es kein gemeinsames Objekt (oder prototypische Vererbung) zwischen den Komponenten gibt. Aber ich denke, dass ist das, was Sie suchen - Sie wollen, dass FooDirective und App dasselbe (Scope) Objekt teilen, richtig? Wenn ja, glaube ich nicht, dass es irgendetwas in Angular 2.

entspricht

Ich bezweifle, dass Sie dieses mögen werde, aber das Beste, was ich tun konnte (das unterscheidet sich von @ Thierry Ansatz) ist zu Verwenden Sie die div als "gemeinsames Objekt" (anstelle der Richtlinie). Die Richtlinie HostBinding verwendet auf den div, um den Wert zu einem Datenattribut zu speichern ruft dann die Komponente diesen Wert in der Vorlage, eine lokale Variable mit einem Verweis auf das div/shared-Objekt zu erhalten:

import {Component, Directive, Input, HostBinding} from '@angular/core'; 

@Directive({selector: '[foo]'}) 
class FooDirective { 
    @Input() id:string; 
    @HostBinding('attr.data-bar') bar; 
    ngOnInit() { 
    this.bar = 'This is "bar" I actually need. It is taken from DB lets say...' + this.id; 
    } 
} 

@Component({ 
    selector: 'my-app', 
    template: `{{title}}<p> 
    <div #div1 foo id="2"> 
     This is random content 1: {{div1.getAttribute('data-bar')}} 
    </div>`, 
    directives: [FooDirective] 
}) 
export class AppComponent { 
    title = `Angular - RC.1`; 
} 

Plunker

ich mag @ Thierry Ansatz besser als das, was ich oben zeigen, aber ich dachte, ich würde schreiben, was ich um mit ohnehin liebäugelt.

+0

Danke für die Antwort, aber ich versuche immer noch," weniger Arbeit "für meine Firma Designer zu machen. Ich meine, sie benutzen bereits meine Direktive von Angular 1 und ich sagte ihnen "Add 'foo' für jedes Element und du wirst einen magischen Wert in' {{bar}} '" haben. Ich kann nicht zu ihnen sagen: "Ich habe ein besseres Werkzeug mit eckigen 2 gemacht, aber jetzt müssen Sie mehr Arbeit hinzufügen, um das gleiche Ergebnis zu erzielen ..." Und ich glaube immer noch, dass es möglich ist, es mit Angular 2 zu machen Moment versuche ich mit strukturellen Anweisungen (* foo) –