2013-09-26 18 views

risposta

126

È possibile utilizzare $broadcast dal padre per un figlio:

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

violino di lavoro: http://jsfiddle.net/wUPdW/2/

UPDATE: C'è un'altra versione, meno accoppiati e più testabile:

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

È davvero fantastico! Ma cosa succede se non si vuole sapere dove si trova l'ambito del chiamante (intendo in '$ scope. $ Parent' o in $ $ scope. $ Parent. $ Parent', ecc.)? Ah, sì: passa una richiamata in params! :) – user2173353

+0

@ user2173353 hai perfettamente ragione; c'è un altro modo: '$ emit' da un bambino a un genitore. Penso che sia il momento di aggiornare la mia risposta .. – Cherniv

+0

È una buona idea chiamare l'ascoltatore globale dove si trova somwhere, controller figlio in questo caso? Non è antipattern e difficile da testare più tardi? Non dovremmo usare iniezioni o smth? – calmbird

27

Mi permetto di suggerire un'altra soluzione:

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


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

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

meno codice e utilizzando l'ereditarietà prototipo.

Plunk

+0

Qualcuno potrebbe spiegare se questo approccio è migliore dell'approccio basato sugli eventi sopra menzionato in quali casi e, in caso affermativo, perché? cosa succede se si dispone di gerarchia multi lvl w controllori figlio? questo funzionerebbe se obj.get è definito all'interno di un controller figlio all'interno di un controller figlio, a condizione che nessuno dei controller abbia definito lo stesso nome di funzione? Grazie in anticipo. – ZvKa

+0

Interessante ... grazie per il commento, ciò che mi ha stancato è che pensavo che l'ereditarietà dell'ambito prototipo/angularjs di js si applicava solo a una direzione .... child -> scope genitore o figlio -> scope genitore, non l'altro modo intorno .... ma credo che mi manchi qualcosa @ _ @ – ZvKa

+1

Lasciatemi correggere ciò che ho detto che non è completamente vero. Hai ragione in quello che hai detto: l'ereditarietà dell'ambito si applica solo a una direzione solo .... figlio -> genitore. Quello che effettivamente sta succedendo qui è che se si definisce $ scope.get in ambito figlio, 'get' verrà definito solo su scope figlio (a volte definito come definizione primitiva). Ma quando si definisce $ scope.obj.get, allora l'ambito figlio cercherà obj che è definito sull'ambito genitore, che è sopra la gerarchia. – Canttouchit

9

Registro Funzione del bambino sul genitore quando il bambino è in fase di inizializzazione. Ho usato la notazione "as" per chiarezza nel template.

MODELLO

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

CONTROLLORI

... 
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";  
    }; 
} 

"Ma", si dicono: "ng-initisn't supposed to be used this way!". Beh, sì, ma

  1. che la documentazione non spiega perché no, e
  2. non credo di documentazione degli autori considerati tutti i possibili casi di utilizzo per esso.

Dico questo è un buon uso per questo. Se vuoi farmi una votazione, per favore commenta con le ragioni! :)

Mi piace questo approccio perché mantiene i componenti più modulari. Gli unici attacchi sono nel modello, e significa che

  • il bambino controller non deve sapere nulla di quale oggetto per aggiungere la funzione in (come nella risposta di @ canttouchit)
  • controllo padre può essere utilizzato con qualsiasi altro controllo figlio che ha una funzione get
  • non necessita di radiodiffusione, che otterrà molto brutto in una grande applicazione a meno che non si controlla strettamente lo spazio dei nomi evento

Questo approccio si avvicina di più a stretto contatto Tero's idea of modularising with directives (nota quello nella sua modularis ed esempio, contestants viene passato dalla direttiva madre alla direttiva "figlio" NEL MODELLO).

In effetti un'altra soluzione potrebbe essere considerare l'implementazione di ChildCntl come una direttiva e utilizzare il binding & per registrare il metodo init.

+1

So che questo è un vecchio post, ma questa sembra una cattiva idea perché il genitore può mantenere un riferimento al bambino dopo che il bambino è stato distrutto. –

Problemi correlati