2013-06-14 12 views
27

Dajemy pierwszą próbę na niestandardowych dyrektywach AngularJS.AngularJS - Uzyskaj izolowany zakres w funkcji linku dyrektywy

Mam problem z używaniem (lub zrozumieniem ...) izolowanego zakresu w funkcji łącza dyrektywy.

Oto kod tej części mojej aplikacji:

view.html

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

request jest zmienną opublikowany w zakresie viewCtrl zawierający xml ciąg wniosku.

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

raw-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> 

Nie rozumiem dlaczego ID correclty pokazany gdy modalnych wyskakuje, ale gdy próbuję console.log() nim, jego wartość jest niezdefiniowana.

Może się mylę z izolowaną wartością zakresu (= i @).

Dziękuję za przeczytanie. :)

+0

Jest to całkowity domysły, ale to „id” specjalne jakoś bo „id” podstawowa część DOM i Angular nie będzie właściwie mapować go do twojej dyrektywy z tego powodu? Czy próbowałeś zmienić nazwę tego atrybutu, aby sprawdzić, czy pomaga on lepiej działać? – blaster

+0

Dużo pomaga, jeśli możesz postawić skrzypce (jsfiddle.com/plnkr.co). –

+0

@blaster: To samo działo się z "tytułem" i nie jest podstawowym podpisem DOM. :) – pdegand59

Odpowiedz

34

Właściwości zakresu izolacji powiązane z @ nie są natychmiast dostępne w funkcji łączenia. Trzeba użyć $observe:

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

Szablon działa prawidłowo ponieważ kątowe automatycznie aktualizuje właściwość wyizolować zakres id dla Ciebie. A kiedy się zaktualizuje, Twój szablon automatycznie się zaktualizuje.

Jeśli tylko przejazdem sznurki, można po prostu ocenić wartości raz zamiast korzystania @ oprawa:

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

Jednak w twoim przypadku, ponieważ chcesz użyć właściwości w szablonach, należy użyć @.

Jeśli nie korzystasz z szablonów, wówczas @ jest przydatny, gdy wartości atrybutów zawierają, na przykład title="{{myTitle}}". Wtedy potrzeba użycia $observe staje się bardziej widoczna: twoja funkcja łączenia może chcieć coś zrobić za każdym razem, gdy zmieni się wartość myTitle.

+0

Dzięki za wyjaśnienia tezy. Próbowałem także łączyć 'console.log()' z '$ timeout (function() {...}, 0, true);' i wartość '$ scope.id' była poprawnie ustawiona. Jak już wspomniałeś, pomyślałem o użyciu obiektu '$ attr', ale ponieważ potrzebowałem tych wartości w szablonie, potrzebne było '@'. Teraz wszystko działa zgodnie z przeznaczeniem! :) – pdegand59

+0

Czy użyłbyś funkcji $ obserwuj dla atrybutów wiązanych dwukierunkowo? Mam do czynienia z tym samym problemem z nieokreślonym, kiedy go loguję, ale działa wewnątrz szablonu. Atrybuty są właściwościami modelu (prymitywami i obiektami) z zakresu nadrzędnego, dlatego próbuję wiązania "=". Jak uzyskać console.log, aby poprawnie zarejestrować wartość? – CMCDragonkai

+0

Przy okazji właściwość modelu jest oczywiście wypełniana z żądania AJAX, więc jest pusta, gdy się zaczyna. – CMCDragonkai

9

Jest to celowe i ma związek z kolejnością kompilacji oraz różnicą między znakami "@" i "=".

Niektóre fragmenty 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 dla linku do grupy google ... dobra lektura. –

0

dobrze, żadna z powyższych odpowiedzi faktycznie wymienione Jednym z kluczowych aspektów, nawet z „=”, to nie wydaje mi się, można uzyskać dostęp do funkcji wewnątrz zakresu łącza bezpośrednio jak poniżej,

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

ale można uzyskać dostęp do zakresu w funkcji wewnętrznego,

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

, więc wydaje mi się, że może wystąpić opóźnienie w czasie, gdy scope.data może być dostępny.

Powiązane problemy