2013-03-15 15 views
7

Jeśli chodzi o dyrektywy AngularJS, natknąłem się na sytuację, w której wzywam dyrektywę z innej dyrektywy i mam następujące pytania.Zagnieżdżanie dyrektyw w dyrektywach

  1. Dlaczego nie mogę odwoływać się do scope.bindValue w funkcji mojego linku? Czy istnieje sposób można obliczyć wartość z scope.bindValue i ustawić go na zakres?
  2. Dlaczego można powiązać subdirective za pomocą "@" w zakresie: {}, ale nie używać scope.value = attrs.value w funkcji łącza?

Wszystko poniżej można zobaczyć na http://jsfiddle.net/sdg9/AjDtt/13/

HTML:

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

wyjściowa:

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 

Odpowiedz

13

Interpolowane atrybuty (tj. Atrybuty korzystające z {{}} s) i izolujące właściwości zakresu zdefiniowane za pomocą "@" nie są dostępne, gdy działa funkcja łącza. Aby uzyskać wartości (asynchronicznie), należy użyć wartości attrs.$observe() (lub scope.$watch(@ property here, ...)).

Tak, scope.bindValue nie jest dostępny, gdy próbujesz go użyć.

Podobnie w Twojej podkatalogu atrybut value ma wartość {{}}, więc jego wartość również nie będzie dostępna, gdy próbujesz go użyć. Musisz również zdefiniować właściwość dyrektywy "@".

Praca .

Powodem wymagania asynchronicznego jest to, że elementy wewnątrz {{}} s mogą ulec zmianie, a zwykle chcesz, aby twoja dyrektywa zauważyła (i zrobiła coś - np. Zaktualizowała wartości "addOne"). "@" jest zwykle używany w przypadku zakresów izolatów, gdy wartość atrybutu zawiera {{}} s.

Jeśli wartości atrybutów są stałe i nie zamierzasz używać wartości w szablonie (lub templateUrl), nie powinno się używać znaku "@". W funkcji łączenia wystarczy użyć attrs.attrName, jeśli wartość jest łańcuchem lub scope.$eval(attrs.attrName), jeśli atrybut jest liczbą lub wartością logiczną (lub parseInt(attrs.attrName), jeśli wiesz, że jest liczbą).

+0

Dzięki temu udało się uzyskać tę operację za pomocą attrs. $ Observe(). Pozostanę przy użyciu "@" w podkatalogu, ponieważ powinno to wystarczyć dla moich scenariuszy. http://jsfiddle.net/sdg9/AjDtt/16/ – Steven

+1

@Steven, tworzyłem skrzypce w tym samym czasie co ty :) W moim skrzypcach pokazuję również, jak uzyskać 'wartość' w pod-przewodniku. Zaktualizowałem również moją odpowiedź, dodając trochę więcej informacji. –

+3

w odniesieniu do "Jeśli wartości atrybutów są stałe," @ "prawdopodobnie nie powinno być używane", co z tym, kiedy zagnieżdżam dyrektywy? Moja zewnętrzna dyrektywa może wyglądać jak , ale ponieważ używa szablonu templateURL, wywołuje moją dyrektywę podrzędną za pomocą atrybutu interpolowanego. Czy to jest prawidłowe użycie szablonuURL, czy też powinienem samemu konstruować ten element poprzez angular.element i dodawać go do szablonu? Później wydaje mi się, że mam dużo dodatkowej pracy, aby uniknąć atrybutów interpolowanych. – Steven