2013-03-15 8 views
7

In Bezug auf AngularJS-Direktiven bin ich in eine Situation geraten, in der ich eine Direktive innerhalb einer anderen Direktive anrufe und ich habe die folgenden Fragen.Verschachteln von Direktiven innerhalb von Direktiven

  1. Warum kann ich scope.bindValue in meiner Link-Funktion nicht referenzieren? Gibt es eine Möglichkeit, einen Wert von scope.bindValue zu berechnen und auf den Bereich zu setzen?
  2. Warum kann das Unterverzeichnis binden mit "@" im Bereich: {}, aber nicht verwenden scope.value = attrs.value in der Link-Funktion?

Alle unten können bei http://jsfiddle.net/sdg9/AjDtt/13/

HTML zu sehen:

<directive bind-value="12" value="7"></directive> 

JS:

var myApp = angular.module('myApp', []); 
var commonTemplate = '<div>{{name}} bind-value is: {{bindValue}} </div><div>{{name}} value is: {{value}} </div><div>{{name}} add one to bind-value is: {{addOneBindValue}} </div><div>{{name}} add one to value is: {{addOneValue}} </div><br/>'; 

myApp.directive('directive', function() { 
    return { 
     scope: { 
      bindValue: "@", 
     }, 
     template: commonTemplate + '<br/><sub-directive bind-value="{{value}}" value="{{value}}"></sub-directive>', 
     restrict: 'E', 
     link: function (scope, element, attrs) { 
      scope.name = "Directive"; 
      scope.value = attrs.value; 
      scope.addOneBindValue = parseInt(scope.bindValue) + 1; 
      scope.addOneValue = parseInt(scope.value) + 1; 
     } 
    }; 
}); 


myApp.directive('subDirective', function() { 
    return { 
     scope: { 
      bindValue: "@" 
     }, 
     template: commonTemplate, 
     restrict: 'E', 
     link: function (scope, element, attrs) { 
      scope.name = "SubDirective"; 
      scope.value = attrs.value; 
      scope.addOneBindValue = parseInt(scope.bindValue) + 1; 
      scope.addOneValue = parseInt(scope.value) + 1; 
     } 
    }; 
}); 

Ausgang:

Directive bind-value is: 12 
Directive value is: 7 
Directive add one to bind-value is: null <--- why? 
Directive add one to value is: 8  

SubDirective bind-value is: 7 
SubDirective value is:      <--- why? 
SubDirective add one to bind-value is: null 
SubDirective add one to value is: null 

Antwort

13

Interpolierte Attribute (d. H. Attribute, die {{}} s verwenden) und Bereichsdefinitionen, die mit '@' definiert sind, sind nicht verfügbar, wenn die Verknüpfungsfunktion ausgeführt wird. Sie müssen attrs.$observe() (oder scope.$watch(@ property here, ...)) verwenden, um die Werte (asynchron) abzurufen.

So, scope.bindValue ist nicht verfügbar, wenn Sie versuchen, es zu verwenden.

In ähnlicher Weise hat das Attribut value in Ihrer Unterdirektive {{}} s, so dass sein Wert auch nicht verfügbar ist, wenn Sie versuchen, es zu verwenden. Sie müssen dazu auch eine '@' - Direktive definieren.

Arbeiten fiddle.

Der Grund für die asynchrone Anforderung ist, dass die Elemente in den {{}} s sich ändern können, und normalerweise möchten Sie Ihre Anweisung bemerken (und dann etwas tun - wie die "addOne" -Werte aktualisieren). '@' wird normalerweise mit Isolate-Bereichen verwendet, wenn der Attributwert {{}} s enthält.

Wenn Attributwerte Konstanten sind und Sie nicht die Werte in einer Vorlage (oder templateUrl) verwenden, sollte '@' wahrscheinlich nicht verwendet werden. Verwenden Sie in der Verknüpfungsfunktion einfach attrs.attrName, wenn der Wert eine Zeichenfolge ist, oder scope.$eval(attrs.attrName), wenn das Attribut eine Zahl oder ein boolescher Wert ist (oder parseInt(attrs.attrName), wenn Sie wissen, dass es eine Zahl ist).

+0

Dank konnte diese Arbeit mit Attras. $ Beobachten(). Ich bleibe bei der Verwendung von '@' auf dem Unterverzeichnis, da dies für meine Szenarien ausreichend sein sollte. http://jsfiddle.net/sdg9/AjDtt/16/ – Steven

+1

@Steven, ich schuf eine Geige, während du warst :) In meiner Geige zeige ich auch, wie man "Wert" in die Subdirektion bringt. Ich habe auch meine Antwort mit einigen weiteren Informationen aktualisiert. –

+3

in Bezug auf "Wenn Attributwerte Konstanten sind, sollte '@' wahrscheinlich nicht verwendet werden" Was ist, wenn ich Direktiven neste? Meine äußerste Direktive kann wie aussehen, aber da sie eine templateURL verwendet, ruft sie meine Unteranweisung über ein interpoliertes Attribut auf. Ist das die korrekte Verwendung von templateURL oder soll ich das Element selbst über angle.element konstruieren und zur Vorlage hinzufügen? Das spätere fühlt sich für mich sehr an, um interpolierte Attribute zu vermeiden. – Steven