2013-06-14 15 views
27

Sto dando una prima prova alle direttive personalizzate AngularJS.AngularJS - Accesso all'ambito isolato nella funzione di collegamento della direttiva

Sto riscontrando problemi nell'utilizzo (o nella comprensione ...) dell'ambito isolato nella funzione di collegamento della direttiva.

Ecco il codice di questa parte della mia app:

view.html

... 
<raw-data id="request-data" title="XML of the request" data="request">See the request</raw-data> 
... 

request è una variabile pubblicato nel campo di applicazione della viewCtrl che contiene la stringa di XML di una richiesta.

rawData.js

directives.directive('rawData', function() { 

    return { 
     restrict : 'E', 
     templateUrl : 'partials/directives/raw-data.html', 
     replace : true, 
     transclude : true, 
     scope : { 
      id : '@', 
      title : '@', 
      data : '=' 
     }, 
     link : function($scope, $elem, $attr) { 
      console.log($scope.data); //the data is correclty printed 
      console.log($scope.id); //undefined 
     } 
    }; 
}); 

prime data.html

<div> 
    <!-- Button to trigger modal --> 
    <a href="#{{id}}Modal" role="button" class="btn" data-toggle="modal" ng-transclude></a> 

    <!-- Modal --> 
    <div id="{{id}}Modal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="{{id}}Modal" aria-hidden="true"> 
     <div class="modal-header"> 
      <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> 
      <h3 id="myModalLabel">{{ title }}</h3> 
     </div> 
     <div class="modal-body"> 
      <textarea class="input-block-level" rows="10">{{ data }}</textarea> 
     </div> 
     <div class="modal-footer"> 
      <!-- <button class="btn" ng-click="toggleTagText('')">{{'cacher'}} l'image</button> --> 
      <button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">Fermer</button> 
     </div> 
    </div> 
</div> 

Non capisco il motivo per cui l'ID viene correclty mostrato quando il pop modali, ma quando provo a console.log() esso, il suo valore non è definito.

Forse ho sbagliato con il valore dello scope isolato (= e @).

Grazie per la lettura. :)

+0

Si tratta di congetture totale, ma è "id" speciale in qualche modo, perché "id" una parte fondamentale del DOM e Angular non verranno mappati correttamente nella tua direttiva per questo motivo? Hai provato a rinominare quell'attributo per vedere se aiuta a funzionare meglio? – blaster

+0

Aiuta molto se riesci a mettere su un violino (jsfiddle.com/plnkr.co). –

+0

@blaster: lo stesso sta accadendo con il "titolo" e non è un elemento di base del DOM. :) – pdegand59

risposta

34

Le proprietà dell'ambito isolate associate a @ non sono immediatamente disponibili nella funzione di collegamento. È necessario utilizzare $observe:

$attr.$observe('id', function(value) { 
    console.log(value); 
}); 

Il modello funziona correttamente perché angolare aggiorna automaticamente isolare proprietà ambito id per voi. E quando si aggiorna, anche il tuo modello si aggiorna automaticamente.

Se siete solo di passaggio le stringhe, si può semplicemente valutare i valori una volta invece di utilizzare @ vincolante:

link: function($scope, $elem, $attr) { 
    var id = $attr.id; 
    var title = $attr.title 
    console.log(id, title); 
} 

Tuttavia, nel tuo caso, dal momento che si desidera utilizzare le proprietà di modelli, si dovrebbe usare @.

Se non si sta utilizzando i modelli, quindi @ è utile quando i valori degli attributi contengono {{}} s – esempio, title="{{myTitle}}". Quindi la necessità di usare $observe diventa più evidente: la tua funzione di collegamento potrebbe voler fare qualcosa ogni volta che cambia il valore di myTitle.

+0

Grazie per queste spiegazioni. Ho anche provato a racchiudere 'console.log()' con '$ timeout (function() {...}, 0, true);' e il valore di '$ scope.id' è stato impostato correttamente. Come hai detto, ho pensato di usare l'oggetto '$ attr', ma poiché avevo bisogno di questi valori nel modello, era necessario il '@'. Ora tutto funziona come previsto! :) – pdegand59

+0

Utilizzeresti $ observ per attributi binded a due vie? Sto affrontando lo stesso problema di indefinito quando lo registro, ma funziona all'interno del modello. Gli attributi sono proprietà del modello (primitive e oggetti) dall'ambito genitore, quindi ho provato l'associazione '='. Come si ottiene console.log per registrare correttamente il valore? – CMCDragonkai

+0

La proprietà del modello viene ovviamente popolata da una richiesta AJAX, quindi è vuota quando viene avviata. – CMCDragonkai

9

Questo è intenzionale e ha a che fare con l'ordine di compilazione e la differenza tra "@" e "=".

Alcuni estratti da this Google Groups discussion with input from Misko:

@ and = do very different things. One copies the attribute value (which may be interpolated) and the other treats the attribute value as an expression.

@attrs are not $interpolated until later, so they are not available at link time. If you want to do something with them in the link function you either need to $interpolate yourself manually

+0

+1 per il collegamento al gruppo di google ... buona lettura. –

0

bene, nessuna delle risposte di cui sopra in realtà menzionati un aspetto chiave, anche con '=', non sembra a me è possibile accedere l'ambito all'interno funzione di collegamento direttamente come il seguente,

scope: { 
    data: '=', 
}, 
link: function(scope, elem, attrs) { 
    console.debug(scope.data); // undefined 

ma è possibile accedere l'ambito della funzione interna,

link: function(scope, elem, attrs) { 
    scope.saveComment = function() { 
     console.debug(scope.data); 

quindi mi sembra che ci possa essere un ritardo quando scope.data può essere disponibile.

Problemi correlati