2013-03-01 17 views
35

Próbuję uzyskać dostęp do atrybutów dyrektywy w funkcji kontrolera. Jednak do czasu uzyskania dostępu do niego jest on niezdefiniowany. Zauważyłem, że jeśli wykonuję prosty timer, działa. Czy istnieje sposób na wykonanie kodu tylko po dyrektywie, a jego zakresy są gotowe i gotowe do użycia?Dyrektywy AngularJS przypisują dostęp do kontrolera

Zrobiłem z nim skrzypce. Upewnij się, że konsola jest otwarta. http://jsfiddle.net/paulocoelho/uKA2L/1/

Oto kod używam na skrzypcach:

<div ng-app="testApp" > 
    <testcomponent text="hello!"></testcomponent> 
</div> 
var module = angular.module('testApp', []) 
    .directive('testcomponent', function() { 
    return { 
     restrict: 'E', 
     template: '<div><p>{{text}} This will run fine! </p></div>', 
     scope: { 
      text: '@text' 
     }, 
     controller: function ($scope, $element) { 
      console.log($scope.text); // this will return undefined 
      setTimeout(function() { 
       console.log($scope.text); // this will return the actual value... 
      }, 1000); 
     }, 
     link: function ($scope, $element, $attrs) { 
      console.log($scope.text); 
      setTimeout(function() { 
       console.log($scope.text); 
      }, 1000); 
     } 
    }; 
}); 

Odpowiedz

25

Co działa to, jeśli ustawisz

scope.text = $attrs.text; 

wewnątrz łączenie i funkcji kontrolera. To będzie działać tylko na początku, ponieważ nie ma opcji 2way-databinding. Możesz jednak użyć $attrs.observe.

See skrzypce: http://jsfiddle.net/JohannesJo/nm3FL/2/

+0

Tak, pracuje dla mnie :) dzięki mężczyzna – PCoelho

+1

to zawiedzie strzępienie. ponieważ 'attrs.text' jest nieznany. –

+1

@DougChamberlain Możesz użyć JSDoc, aby obejść to. Coś jak '' @param {string} attrs.text'' powinno rozwiązać twój problem. –

1

Funkcja Link nazywa zanim $ strawienia pętlę, w tym zmienne chwila zakres są niezdefiniowane. Spójrz na this chapter i this other, aby zrozumieć, w jaki sposób działa funkcja link. Korzystasz tylko z funkcji link do definiowania zegarków i/lub zachowań dla dyrektywy, a nie do manipulowania modelem, odbywa się to w kontrolerach.

+0

To nie wszystko prawda. Zmienne zakresowe są definiowane przez czas działania funkcji po-link i można manipulować modelem danych w funkcji łącza. Kontrolery są potrzebne tylko w przypadku dyrektywy, jeśli planujesz użyć jej do komunikacji z inną dyrektywą za pośrednictwem właściwości require. Kontroler faktycznie uruchamia się najpierw, a następnie pre-link, idąc całą drogę w dół drzewa dom do liści, a następnie po połączeniu z powrotem do katalogu głównego. Przejdź do tego wątku, aby uzyskać wyjaśnienia. https://stackoverflow.com/questions/24615103/angular-directives-when-and-how-to-use-compile-controller-pre-link-and-post –

23

W odosobnionym zakresie nie można uzyskać dostępu do właściwości zakresu lokalnego zdefiniowanej przez "@" w funkcji łączenia. Jak już wspomniano @remigio, takie właściwości zakresu lokalnego są w tym momencie undefined. $ attrs. $ observe() lub $ scope. Funkcja $ watch() musi zostać użyta do asynchronicznego uzyskania wartości (interpolowanej).

Jeśli podajesz wartość stałą w atrybucie (tzn. Nie jest wymagana interpolacja, tj. Wartość atrybutu nie zawiera żadnych {{}} s), nie ma potrzeby stosowania "@" lub $ obserwatora lub $ watch. Możesz użyć $ attrs. nazwa_atrybutu raz jak sugeruje @hugo lub jeśli podajesz liczbę lub wartość logiczną i chcesz uzyskać odpowiedni typ, możesz jednorazowo użyć $ scope. $ Eval ($ attrs. nazwa_atrybutu).

Jeśli użyjesz '=' do powiązania bazy danych z właściwością zakresu lokalnego z właściwością zakresu nadrzędnego, wartość właściwości będzie dostępna w funkcji łączenia (nie ma potrzeby $ obserwuj lub $ zegarek lub $ eval).

+0

+1 To doprowadzało mnie do szału. – GFoley83

+0

+1 Dziękuję za wyjaśnienie! –

0

Jeśli dostęp do tej wartości z Twojego dyrektywy wstawić w widoku za pomocą dyrektywy można uzyskać dostęp do tego atrybutu za pomocą interfejsu API $ kompilacji i robi coś jak ten

var string = "<div> " + scope.text + "</div>"; 
$compile(string)(scope, function(cloned, scope){ 
     element.append(cloned); 
}); 
7

Od Kątowymi 1.3, można użyć bindToController. Oto próbka tego, jak go używam. Tu dodam atrybut do zakresu, a następnie użyć bindToController w obsłudze, że wewnątrz sterownika:

var module = angular.module('testApp', []) 
    .directive('testcomponent', function() { 
    return { 
     restrict: 'E', 
     template: '<div><p>{{text}} This will run fine! </p></div>', 
     scope: { 
      text: '@text' 
     }, 
     controller: function() { 
      console.log(this.text); 
     }, 
     controllerAs: 'vm', 
     bindToController: true 
    }; 
}); 

kątowe 1.3 wprowadza nową właściwość do definicji dyrektywy obiektu zwanego bindToController, który robi dokładnie to co mówi. Gdy wartość ustawiona jest na wartość true w dyrektywie z izolowanym zasięgiem, który używa kontrolek A, , właściwości komponentu są przypisywane kontrolerowi, a nie zakresowi .Oznacza to, że Angular upewnia się, że gdy instancja kontrolera jest utworzona, początkowe wartości izolowanych powiązań zakresu są dostępne w tym zakresie w postaci , a przyszłe zmiany są również automatycznie dostępne .

+1

To nie działa dla mnie, this.text jest niezdefiniowany. – rjh

+0

@rjh Czy przekazałeś "tekst" podczas wywoływania dyrektywy w ten sposób? '' – Neel

5

Zamiast korzystania $scope uzyskać dyrektywy przypisuje wartość, osobiście wolę korzystania $attrs dla funkcji controller, czy tylko attrs na 3rd parametr funkcji link. Nie mam problemu, gdy uzyskać wartość atrybuty z controller wykonując kod bez limitu czasu:

var module = angular.module('testApp', []) 
    .directive('testcomponent', function() { 
    return { 
    restrict: 'E', 
    template: '<div><p>{{text}} This will run fine! </p></div>', 
    scope: { 
     text: '@text' 
    }, 
    controller: ['$scope','$attrs', function ($scope, $attrs) { 
     console.log($attrs.text); // just call to the $attrs instead $scope and i got the actual value 
     $scope.text = $attrs.text; //assign attribute to the scope 
    }] 
    }; 
}); 
Powiązane problemy