2013-03-15 14 views
7

Per quanto riguarda le direttive AngularJS Mi sono imbattuto in una situazione in cui sto chiamando una direttiva da un'altra direttiva e ho le seguenti domande.Direttive di annidamento all'interno delle direttive

  1. Perché non è possibile fare riferimento a scope.bindValue nella funzione di collegamento? C'è un modo per calcolare un valore da scope.bindValue e impostarlo su scope?
  2. Perché il bind indiretto utilizza "@" nell'ambito: {} ma non utilizza scope.value = attrs.value nella funzione di collegamento?

Tutto quanto qui di seguito può essere visto in 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; 
     } 
    }; 
}); 

uscita:

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 

risposta

13

Gli attributi interpolati (ovvero gli attributi che utilizzano {{}}) e isolano le proprietà dell'ambito definite con '@' non sono disponibili quando viene eseguita la funzione di collegamento. È necessario utilizzare attrs.$observe() (o scope.$watch(@ property here, ...)) per ottenere i valori (in modo asincrono).

Quindi, scope.bindValue non è disponibile quando si sta tentando di utilizzarlo.

Analogamente, nella sottodirettiva, l'attributo value ha {{}}, quindi il suo valore non sarà disponibile anche quando si sta tentando di utilizzarlo. È inoltre necessario definire una proprietà direttiva '@' per questo.

Lavoro fiddle.

Il motivo per il requisito asincrono è che gli elementi all'interno di {{}} possono cambiare e normalmente si desidera che la direttiva noti (e quindi esegui qualcosa, ad esempio aggiorna i valori "addOne"). '@' viene normalmente utilizzato con ambiti isolati quando il valore dell'attributo contiene {{}} s.

Se i valori di attributo sono costanti e non si useranno i valori in un modello (o templateUrl), probabilmente "@" non dovrebbe essere utilizzato. Nella funzione di collegamento, è sufficiente utilizzare attrs.attrName se il valore è una stringa o scope.$eval(attrs.attrName) se l'attributo è un numero o booleano (o parseInt(attrs.attrName) se si sa che è un numero).

+0

Grazie è riuscito a farlo funzionare con attrs. $ Observ(). Mi limiterò a utilizzare '@' nella sottodirettiva poiché dovrebbe essere sufficiente per i miei scenari. http://jsfiddle.net/sdg9/AjDtt/16/ – Steven

+1

@Steven, stavo creando un violino nello stesso tempo in cui eri :) Nel mio violino, mostro anche come ottenere 'value' nella subDirective. Ho anche aggiornato la mia risposta con alcune informazioni in più. –

+3

in merito a "Se i valori degli attributi sono costanti, '@' probabilmente non dovrebbe essere usato" e quando si annidano le direttive? La mia direttiva più esterna può apparire come ma poiché sta usando un modelloURL, sta chiamando la mia direttiva secondaria tramite un attributo interpolato. È questo l'uso corretto di templateURL o dovrei costruire l'elemento me stesso tramite angular.element e aggiungerlo al template? Più tardi mi sembra un sacco di lavoro extra per evitare attributi interpolati. – Steven

Problemi correlati