2014-12-26 15 views
5

Vorrei capire perché quando si utilizza uno ng-repeat con un determinato controller sull'elemento della ripetizione, il genitore di quell'elemento e il nonno di quell'elemento sono lo stesso controller. Mi aspettavo che il nonno fosse il genitore del controllore genitore, non lo stesso controller.

Ecco il codice per chiarire questo

HTML

<div ng-controller="MainController"> 
    {{name}} 
    <div ng-controller="SecondController"> 
    {{name}} 
    <ul> 
     <li ng-repeat="item in list" ng-controller="ItemController"> 
     {{item.name}} {{$parent.name}} {{myDad}} {{myGrandpa}} 
     </li> 
    </ul> 
    <div ng-controller="ThirdController"> 
     {{name}} {{$parent.name}} {{myDad}} {{myGrandpa}} 
    </div> 
    </div> 
</div> 

JS

angular.module('app', []); 


angular.module('app') 
    .controller('MainController', function($scope) { 
    $scope.name = "MainController"; 
}) 
.controller('SecondController', function($scope) { 
    $scope.name = "SecondController"; 
    $scope.list = [ 
    {'name': 'aaa'} 
    ]; 
}) 
.controller('ItemController', function($scope) { 
    $scope.name = "ItemController"; 
    $scope.myDad = $scope.$parent.name; 
    $scope.myGrandpa = $scope.$parent.$parent.name; 
}) 
.controller('ThirdController', function($scope) { 
    $scope.name = "ThirdController"; 
    $scope.myDad = $scope.$parent.name; 
    $scope.myGrandpa = $scope.$parent.$parent.name; 
}); 

Qui a que CodePen

+0

Il ng-repeat ha il suo probabilmente, molte altre direttive possono creare i propri scopi, quindi è meglio non fare affidamento su '$ parent'. Le proprietà dell'ambito sono ereditate, quindi se vuoi assicurarti di avere accesso a un certo elemento in un bambino puoi sempre creare un oggetto, come '$ scope.secondData = {};' e accedere a 'secondData' sul tuo scope. –

+0

Ma nel mio caso mi piacerebbe '$ broadcast' qualcosa di forma il nonno dopo una certa funzione sul nipote. Quindi probabilmente '$ rootScope' è l'opzione migliore? – stilllife

risposta

2

In Angular, $ scope eredita e non i controller.

Ogni controller creato da ng-controller crea un nuovo $ scope (childScope) che eredita dall'ambito $ in cui esiste. Penso che si potrebbe voler leggere questo answer per capire come eredita esattamente $ ambito (eredità prototipica).

Si prega di non dover utilizzare "$ parent" per ottenere il nome del $ scope genitore, ad esempio se si rimuoverà $ scope.name da ItemController e si proverebbe a associare {{name }} il tuo modello verrà compilato e collegato e il valore di {{name}} sarà "SecondController" nel tuo esempio.

Per quanto riguarda la trasmissione $, è consigliabile evitare di utilizzare $ rootScope. $ Broadcast poiché invierà un evento a tutti gli ambiti $ nella propria applicazione. Non sono sicuro di ciò che il vostro caso d'uso è, ma se si desidera eseguire un metodo che viene definito nel "MainController", per esempio, si può solo chiamare ad esempio

angular.module('app', []); 


angular.module('app') 
    .controller('MainController', function($scope) { 
    $scope.name = "MainController"; 
    $scope.doSomething = function() { 
    console.log("Do it"); 
    } 
}) 
.controller('SecondController', function($scope) { 
    $scope.name = "SecondController"; 
    $scope.list = [ 
    {'name': 'aaa'} 
    ]; 
}) 
.controller('ItemController', function($scope) { 
    $scope.name = "ItemController"; 
    $scope.myDad = $scope.$parent.name; 
    $scope.myGrandpa = $scope.$parent.$parent.name; 
    $scope.clickItem = function() { 
    console.log("Item clicked"); 
    $scope.doSomething(); // The method from "MainController" will be executed unless ItemController is isolated 
    } 
}) 
.controller('ThirdController', function($scope) { 
    $scope.name = "ThirdController"; 
    $scope.myDad = $scope.$parent.name; 
    $scope.myGrandpa = $scope.$parent.$parent.name; 
}); 
0

per rispondere del tuo commento stion, sì, dovresti usare $ rootScope come broker di messaggi nel tuo sistema.

Per quanto riguarda le specifiche, questo è legato al campo di applicazione della direttiva, un modo migliore per gestire questo codice (per gli altri che può inciampare su questa questione) è la seguente:

<div ng-controller="MainController as main"> 
 
    {{main.name}} 
 
    <div ng-controller="SecondController as second"> 
 
    {{second.name}} 
 
    <ul> 
 
     <li ng-repeat="item in list" ng-controller="ItemController as item"> 
 
     {{item.name}} {{second.name}} {{myDad}} {{myGrandpa}} 
 
     </li> 
 
    </ul> 
 
    <div ng-controller="ThirdController as third"> 
 
     {{name}} {{third.name}} {{myDad}} {{myGrandpa}} 
 
    </div> 
 
    </div> 
 
</div>

questo allevia problemi con l'ambito e consente chiaramente l'accesso al controller appropriato all'interno di una direttiva.

0

Per il tuo commento a voler trasmettere, è possibile utilizzare una funzione come questa e chiamarlo dal bambino:

// in MainController: 
$scope.broadcastMain = function(message) { 
    $scope.$broadcast(message); 
}; 

Poi quella funzione è ereditaria, ma è la chiusura avrà $scope essere la stessa portata che viene creato su, quindi puoi usare $scope.broadcast() per arrivare ai suoi figli. (codepen)