AngularJS-accès à l'enfant champ d'application
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 parent
lire b
sur child
? S'il est nécessaire de définir b
dans parent
, cela ne le rendrait-il pas sémantiquement incorrect en supposant que b
est une propriété qui décrit quelque chose liée à child
et non parent
?
mise à Jour: Penser plus à ce sujet, si plus d'un enfant avait b
cela créerait un conflit pour parent
sur lequel b
pour récupérer. Ma question reste, Quelle est la bonne façon d'accéder à b
de parent
?
6 réponses
Scopes en AngularJS utiliser l'héritage prototypique, lors de la recherche d'une propriété dans un enfant scope l'interprète regardera en haut de la chaîne prototype à partir de l'enfant et continuer aux parents jusqu'à ce qu'il trouve la propriété, pas l'inverse.
vérifier les commentaires de Vojta sur la question https://groups.google.com/d/msg/angular/LDNz_TQQiNE/ygYrSvdI0A0J
en un mot: vous ne pouvez pas accéder à des portées enfant à partir d'un scope parent.
vos solutions:
- définir les propriétés des parents et y accéder auprès des enfants (lire le lien ci-dessus)
- utiliser un service pour partager l'état
- transmettre les données à travers les événements.
$emit
envoie les événements vers le haut aux parents jusqu'à ce que la portée de base et$broadcast
envoie les événements vers le bas. Cela pourrait vous aider à garder les choses sémantiquement correctes.
bien que la réponse de jm-soit la meilleure façon de traiter ce cas, pour référence future, il est possible d'accéder à child scopes en utilisant $$$childHead, $childTail, $nextSibling et $$$prevSibling members. Ceux-ci ne sont pas documentés de sorte qu'ils peuvent changer sans préavis, mais ils sont là si vous vraiment besoin de parcourir des portées.
// get $$childHead first and then iterate that scope's $$nextSiblings
for(var cs = scope.$$childHead; cs; cs = cs.$$nextSibling) {
// cs is child scope
}
Vous pouvez essayer ceci:
$scope.child = {} //declare it in parent controller (scope)
ajouter ensuite dans le régulateur pour enfants (scope):
var parentScope = $scope.$parent;
parentScope.child = $scope;
Maintenant, le parent a accès à l'enfant.
une solution possible est d'injecter le contrôleur enfant dans le contrôleur parent en utilisant une fonction init.
mise en œuvre Possible:
<div ng-controller="ParentController as parentCtrl">
...
<div ng-controller="ChildController as childCtrl"
ng-init="ChildCtrl.init()">
...
</div>
</div>
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 le 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 utilisez la directive ng-controller
et renommez chaque contrôleur en utilisant as
comme je l'ai fait dans l'eg html.
Conseils:
Utilisez le plugin chrome ng-inspector pendant le processus. Il va vous aider à comprendre l'arbre.
Oui, nous pouvons assigner des variables de child controller aux variables de parent controller. C'est une façon possible:
Overview: le but principal du code, ci-dessous, est d'attribuer $scope du contrôleur enfant.variable à $ scope du contrôleur parent.assigner
explication: il y a deux contrôleurs. Dans le html, notez que le contrôleur parent entoure le contrôleur enfant. Cela signifie que le le contrôleur parent sera exécuté avant le contrôleur enfant. Ainsi, setValue() sera d'abord défini et ensuite le contrôle ira au contrôleur enfant. $portée.variable sera assignée comme "enfant". Alors ce champ enfant sera passé comme argument à la fonction de contrôleur parent, où $scope.attribuer obtenez la valeur comme "enfant",
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<script type="text/javascript">
var app = angular.module('myApp',[]);
app.controller('child',function($scope){
$scope.variable = "child";
$scope.$parent.setValue($scope);
});
app.controller('parent',function($scope){
$scope.setValue = function(childscope) {
$scope.assign = childscope.variable;
}
});
</script>
<body ng-app="myApp">
<div ng-controller="parent">
<p>this is parent: {{assign}}</p>
<div ng-controller="child">
<p>this is {{variable}}</p>
</div>
</div>
</body>
</html>
je ne suis pas sûr de savoir si ou de ne pas vous "doit" l'accès de l'enfant au 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 à l'intérieur d'une variable. Que cette variable est référencée dans l'index principal.fichier html en ng-include. Ainsi, lorsque la chaîne de caractères est changée, un nouveau fichier html est chargé dans ce ng-include. À l'intérieur d'un de ces fichiers html j'ai un autre ng-include. Pensez à ce que d'une petite fenêtre dans la première fenêtre. Chaque fois que je change le contenu de ces fenêtres, je change aussi le contenu d'un panneau latéral. Ce panneau latéral est au niveau parent. Mais, quand je vais dans la fenêtre plus petite dans le parent, ce panneau latéral de niveau parent a des liens de navigation qui changent les choses dans la petite fenêtre. Puisque le panneau latéral est au niveau parent et la navigation pour la fenêtre plus petite est prise en charge dans son propre contrôleur à l'enfant, lorsque je clique sur les liens sur le côté du panneau de il a à modifier le contrôleur enfant. Cela peut être une mauvaise programmation. Honnêtement, je ne sais pas. J'ai commencé avec angularjs il y a quelques mois et j'apprends encore. Mais, pour le faire fonctionner pour mon scénario, j'ai fait une fonction dans le champ parent, qui s'appelle lorsque le champ child se charge:
function parent($scope, service) {
setCurrentChildController = function (childScope) {
this.$scope.childScope = childScope;
}
}
function child($scope) {
scope.$parent.setCurrentChildController($scope);
}
donc, maintenant la variable $scope de la société mère.childScope est essentiellement le contrôleur de l'enfant portée. Il a accès à toutes les variables et fonctions au sein de l'enfant. Si c'est la mauvaise programmation et n'importe qui peut venir avec une solution alternative au problème avec mon scénario, ce serait super. Mais, ce n'travail si nécessaire.