AngularJS – Accès à la scope de l’enfant

Si j’ai les contrôleurs suivants:

function parent($scope, service) { $scope.a = 'foo'; $scope.save = function() { service.save({ a: $scope.a, b: $scope.b }); } } function child($scope) { $scope.b = 'bar'; } 

Quelle est la bonne façon de laisser le parent lire b hors de l’ child ? S’il est nécessaire de définir b dans parent , cela ne rendrait-il pas sémantiquement incorrect l’hypothèse que b est une propriété décrivant un élément lié à l’ child et non au parent ?

Mise à jour: En y repensant, si plus d’un enfant avait b cela créerait un conflit pour le parent sur lequel b récupérer. Ma question rest, quelle est la bonne façon d’accéder à b de parent ?

Les étendues dans AngularJS utilisent l’inheritance de prototypage. Lorsque vous recherchez une propriété dans une scope enfant, l’interpréteur recherche la chaîne prototype à partir de l’enfant et continue jusqu’aux parents jusqu’à ce qu’elle trouve la propriété, et non l’inverse.

Consultez les commentaires de Vojta sur le problème https://groups.google.com/d/msg/angular/LDNz_TQQiNE/ygYrSvdI0A0J

En bref: Vous ne pouvez pas accéder aux étendues enfants à partir d’une scope parent.

Vos solutions:

  1. Définir les propriétés dans les parents et y accéder depuis les enfants (lire le lien ci-dessus)
  2. Utiliser un service pour partager l’état
  3. Passer des données à travers des événements. $emit envoie les événements aux parents jusqu’à ce que la scope racine et la $broadcast dissortingbuent les événements vers le bas. Cela pourrait vous aider à garder les choses sémantiquement correctes.

Alors que la réponse de jm est le meilleur moyen de gérer ce cas, il est possible de consulter ultérieurement les scopes enfants à l’aide des membres $$ childHead, $$ childTail, $$ nextSibling et $$ prevSibling d’une étendue. Celles-ci ne sont pas documentées, elles peuvent donc changer sans préavis, mais elles sont là si vous avez vraiment besoin de parcourir les étendues.

 // get $$childHead first and then iterate that scope's $$nextSiblings for(var cs = scope.$$childHead; cs; cs = cs.$$nextSibling) { // cs is child scope } 

Violon

Vous pouvez essayer ceci:

 $scope.child = {} //declare it in parent controller (scope) 

puis dans le contrôleur enfant (scope) append:

 var parentScope = $scope.$parent; parentScope.child = $scope; 

Maintenant, le parent a access à la scope de l’enfant.

Une solution de contournement possible consiste à injecter le contrôleur enfant dans le contrôleur parent à l’aide d’une fonction init.

Mise en oeuvre possible:

 
...
...

Où dans ChildController vous avez:

 app.controller('ChildController', ['$scope', '$rootScope', function ($scope, $rootScope) { this.init = function() { $scope.parentCtrl.childCtrl = $scope.childCtrl; $scope.childCtrl.test = 'aaaa'; }; }]) 

Donc, maintenant, dans ParentController vous pouvez utiliser:

 app.controller('ParentController', ['$scope', '$rootScope', 'service', function ($scope, $rootScope, service) { this.save = function() { service.save({ a: $scope.parentCtrl.ChildCtrl.test }); }; }]) 

Important:
Pour fonctionner correctement, vous devez utiliser la directive ng-controller et renommer chaque contrôleur en utilisant comme je l’ai fait dans le html par exemple.

Conseils:
Utilisez le plug – in chrome ng-inspector pendant le processus. Cela va vous aider à comprendre l’arbre.

Oui, nous pouvons affecter des variables du contrôleur enfant aux variables du contrôleur parent. C’est un moyen possible:

Vue d’ensemble: L’objective principal du code, ci-dessous, est d’affecter $ scope.variable du contrôleur enfant au $ scope.assign du contrôleur parent

Explication: Il existe deux contrôleurs. Dans le code HTML, notez que le contrôleur parent contient le contrôleur enfant. Cela signifie que le contrôleur parent sera exécuté avant le contrôleur enfant. Ainsi, premier setValue () sera défini et ensuite le contrôle ira au contrôleur enfant. $ scope.variable sera assigné comme “enfant”. Ensuite, cette scope enfant sera transmise en tant qu’argument à la fonction du contrôleur parent, où $ scope.assign obtiendra la valeur “enfant”.

      

this is parent: {{assign}}

this is {{variable}}

Je ne suis pas sûr que vous “deviez” ou non “accéder” à la scope de l’enfant depuis le parent, mais c’est possible. Je le sais parce que je l’ai fait moi-même. Voici mon scénario:

J’ai une fonction qui navigue dans mes pages en modifiant la chaîne dans une variable. Que cette variable est référencée dans le fichier index.html principal en tant que ng-include. Ainsi, lorsque la chaîne est modifiée, un nouveau fichier HTML est chargé dans ce ng-include. À l’intérieur de l’un de ces fichiers HTML, j’ai un autre ng-include. Pensez à celui-ci comme une fenêtre plus petite dans la première fenêtre. Chaque fois que je change le contenu de ces fenêtres, je modifie également le contenu d’un panneau latéral. Ce panneau latéral est au niveau parent. Mais, lorsque je vais dans la petite fenêtre du parent, ce panneau latéral de niveau parent contient des liens de navigation qui changent les choses dans la petite fenêtre. Étant donné que le panneau latéral est au niveau parent et que la navigation dans la plus petite fenêtre est effectuée dans son propre contrôleur au niveau enfant, lorsque je clique sur les liens du panneau latéral, il doit modifier le contrôleur enfant. Cela peut être une mauvaise programmation. Honnêtement, je ne sais pas. Je viens de commencer avec angularjs il y a quelques mois et j’apprends encore. Mais, pour que cela fonctionne dans mon scénario, j’ai créé une fonction dans la scope parent, appelée lorsque la scope enfant est chargée:

 function parent($scope, service) { setCurrentChildController = function (childScope) { this.$scope.childScope = childScope; } } function child($scope) { scope.$parent.setCurrentChildController($scope); } 

donc, maintenant la variable $ scope.childScope de la scope parent est essentiellement la scope du contrôleur enfant. Il a access à toutes les variables et fonctions de la scope enfant. Si la programmation est mauvaise et que n’importe qui peut trouver une solution alternative au problème avec mon scénario, ce serait génial. Mais cela fonctionne si nécessaire.