2013-09-26 12 views

Odpowiedz

126

Można użyć $broadcast od rodzica do dziecka:

function ParentCntl($scope) { 

    $scope.msg = ""; 
    $scope.get = function(){ 
     $scope.$broadcast ('someEvent'); 
     return $scope.msg;   
    } 
} 

function ChildCntl($scope) {    
    $scope.$on('someEvent', function(e) { 
     $scope.$parent.msg = $scope.get();    
    }); 

    $scope.get = function(){ 
     return "LOL";  
    } 
} 

skrzypce robocza: http://jsfiddle.net/wUPdW/2/

UPDATE: Jest jeszcze inna wersja, mniej sprzężonej i bardziej testowalny:

function ParentCntl($scope) { 
    $scope.msg = ""; 
    $scope.get = function(){ 
     $scope.$broadcast ('someEvent'); 
     return $scope.msg;   
    } 

    $scope.$on('pingBack', function(e,data) { 
     $scope.msg = data;   
    }); 
} 

function ChildCntl($scope) {    
    $scope.$on('someEvent', function(e) { 
     $scope.$emit("pingBack", $scope.get());   
    }); 

    $scope.get = function(){ 
     return "LOL";  
    } 
} 

Fiddle: http://jsfiddle.net/uypo360u/

+0

To całkiem fajne! Ale co jeśli nie wiesz (chcesz) wiedzieć, gdzie jest zasięg dzwoniącego (mam na myśli w '$ scope. $ Parent' lub' $ scope. $ Parent. $ Parent', etc)? Ach, tak: przekazać wywołanie zwrotne w parametrach! :) – user2173353

+0

@ user2173353 masz rację; jest jeszcze jeden sposób: '$ emit' od dziecka do rodzica. Myślę, że nadszedł czas, aby zaktualizować moją odpowiedź .. – Cherniv

+0

Czy to dobry pomysł, aby zadzwonić do globalnego słuchacza, gdzie jest gdzieś, kontroler dziecka w tym przypadku? Czy to nie jest antipattern i trudne do testowania później? Nie powinniśmy używać zastrzyków lub czegoś podobnego? – calmbird

27

Pozwól mi zaproponować inne rozwiązanie:

var app = angular.module("myNoteApp", []); 


app.controller("ParentCntl", function($scope) { 
    $scope.obj = {}; 
}); 

app.controller("ChildCntl", function($scope) { 
    $scope.obj.get = function() { 
      return "LOL";  
    }; 
}); 

Mniej kod i za pomocą prototypowego dziedziczenia.

Plunk

+0

Czy ktoś mógłby wyjaśnić, czy to podejście jest lepsze od wspomnianego powyżej podejścia opartego na zdarzeniach, w których przypadkach, a jeśli tak, to dlaczego? co jeśli masz wiele kontrolerów potomnych w hierarchii lvl? czy to działałoby, gdyby obiekt obj.get został zdefiniowany w kontrolerze podrzędnym w kontrolerze podrzędnym, o ile żaden z kontrolerów nie ma zdefiniowanej tej samej nazwy funkcji? Z góry dziękuję. – ZvKa

+0

Interesujące ... dziękuję za komentarz, co mnie rzuca, to, że myślałem, że dziedziczenie zakresów js prototypical/angularjs dotyczy tylko jednego kierunku .... child -> parent lub child scope -> parent scope, a nie odwrotnie około .... ale myślę, że brakuje mi czegoś @ _ @ – ZvKa

+1

Pozwól mi poprawić to, co powiedziałem, co nie jest całkowicie prawdziwe. Masz rację w tym, co powiedziałeś: Dziedziczenie zakresu jest stosowane tylko w jednym kierunku .... child -> parent. To, co się tutaj dzieje, to to, że jeśli zdefiniujesz $ scope.get w zasięgu podrzędnym, "get" będzie zdefiniowane tylko w zasięgu podrzędnym (Czasami nazywane prymitywną definicją). Ale kiedy zdefiniujesz $ scope.obj.get, wówczas zakres podrzędny będzie szukał obj, który jest zdefiniowany w nadrzędnym zasięgu, który znajduje się w hierarchii. – Canttouchit

9

Zarejestruj funkcję dziecka na rodzica, gdy dziecko jest inicjalizacji. Użyłem "notacji" jako jasności w szablonie.

WZÓR

<div ng-controller="ParentCntl as p"> 
    <div ng-controller="ChildCntl as c" ng-init="p.init(c.get)"></div> 
</div> 

STEROWNIKI

... 
function ParentCntl() { 
    var p = this; 
    p.init = function(fnToRegister) { 
    p.childGet = fnToRegister; 
    }; 
// call p.childGet when you want 
} 

function ChildCntl() { 
    var c = this; 
    c.get = function() { 
    return "LOL";  
    }; 
} 

"Ale", można powiedzieć, "ng-initisn't supposed to be used this way!". No tak, ale

  1. że dokumentacja nie wyjaśnia, dlaczego nie, i
  2. Nie wierzę, autorzy dokumentacji rozważeniu wszystkich możliwych przypadków użycia dla niego.

Mówię, że to dobry użytek. Jeśli chcesz mnie zlekceważyć, skomentuj powody! :)

Podoba mi się to podejście, ponieważ utrzymuje elementy bardziej modułowe. Jedyne powiązania są w szablonie, a to oznacza, że ​​

  • dziecko Kontroler nie musi nic wiedzieć o który obiekt, aby dodać swoją funkcję (jak w odpowiedzi @ canttouchit za)
  • kontrola rodzic może być używany z dowolnym innym child Control, który posiada funkcję get
  • nie wymaga transmisji, która będzie bardzo brzydki w wielkim aplikacji, chyba że ściśle kontrolować nazw zdarzeń

Takie podejście bliżej podejść Tero's idea of modularising with directives (uwaga w jego modularis ed example, contestants jest przekazywana z nadrzędnej do dyrektywy "potomnej" W SZABLONIE).

Rzeczywiście innym rozwiązaniem może być rozważenie wdrożenia ChildCntl jako dyrektywy i użycie wiązania & do zarejestrowania metody init.

+1

Wiem, że to stary post, ale wydaje się to złym pomysłem, ponieważ rodzic może zachować odniesienie do dziecka po zniszczeniu dziecka. –

Powiązane problemy