AngularJS - Доступ к охвату ребенка
Если у меня есть следующие контроллеры:
function parent($scope, service) {
$scope.a = 'foo';
$scope.save = function() {
service.save({
a: $scope.a,
b: $scope.b
});
}
}
function child($scope) {
$scope.b = 'bar';
}
Какой правильный способ позволить parent
читать b
из child
? Если необходимо определить b
в parent
, не сделает это семантически неправильным, если предположить, что b
является свойством, которое описывает что-то, относящееся к child
, а не parent
?
Обновление: Если подумать об этом, если более одного ребенка имеет b
, он создаст конфликт для parent
, на котором b
будет извлекаться. Мой вопрос остается, какой правильный способ доступа к b
из parent
?
Ответы
Ответ 1
Области в AngularJS используют прототипное наследование, при поиске свойства в области дочерних объектов интерпретатор будет искать цепочку прототипов, начиная с ребенка, и продолжит родителям, пока не найдет свойство, а не наоборот.
Проверьте комментарии Vojta по поводу проблемы https://groups.google.com/d/msg/angular/LDNz_TQQiNE/ygYrSvdI0A0J
Вкратце: вы не можете получить доступ к дочерним областям из родительской области.
Ваши решения:
- Определить свойства у родителей и получить доступ к ним от детей (прочитайте ссылку выше)
- Использовать службу для совместного использования состояния
- Передача данных через события.
$emit
отправляет события вверх родителям до тех пор, пока область корня и $broadcast
не отправит события вниз. Это может помочь вам сохранить вещи семантически правильно.
Ответ 2
В то время как jm-answer - лучший способ справиться с этим случаем, для дальнейшего использования можно получить доступ к дочерним областям с помощью областей $$ childHead, $$ childTail, $$ nextSibling и $$ prevSibling. Они не документированы, поэтому они могут меняться без предварительного уведомления, но они есть, если вам действительно нужно пересекать области.
// get $$childHead first and then iterate that scope $$nextSiblings
for(var cs = scope.$$childHead; cs; cs = cs.$$nextSibling) {
// cs is child scope
}
Fiddle
Ответ 3
Вы можете попробовать следующее:
$scope.child = {} //declare it in parent controller (scope)
затем в дочернем контроллере (область) добавьте:
var parentScope = $scope.$parent;
parentScope.child = $scope;
Теперь родитель имеет доступ к области содержимого.
Ответ 4
Один возможный обходной путь - это ввести дочерний контроллер в родительский контроллер, используя функцию init.
Возможная реализация:
<div ng-controller="ParentController as parentCtrl">
...
<div ng-controller="ChildController as childCtrl"
ng-init="ChildCtrl.init()">
...
</div>
</div>
Где в ChildController
у вас есть:
app.controller('ChildController',
['$scope', '$rootScope', function ($scope, $rootScope) {
this.init = function() {
$scope.parentCtrl.childCtrl = $scope.childCtrl;
$scope.childCtrl.test = 'aaaa';
};
}])
Итак, теперь в ParentController
вы можете использовать:
app.controller('ParentController',
['$scope', '$rootScope', 'service', function ($scope, $rootScope, service) {
this.save = function() {
service.save({
a: $scope.parentCtrl.ChildCtrl.test
});
};
}])
Важно:
Чтобы правильно работать, вам нужно использовать директиву ng-controller
и переименовать каждый контроллер с помощью as
, как я сделал в html, например.
Советы:
Используйте chrome plugin ng-inspector во время процесса. Это поможет вам понять дерево.
Ответ 5
Да, мы можем назначить переменные из дочернего контроллера переменным родительского контроллера. Это один из возможных способов:
Обзор.. Основная цель приведенного ниже кода - назначить дочернему контроллеру $scope.variable родительскому контроллеру $scope.assign
Объяснение: Есть два контроллера. В html обратите внимание, что родительский контроллер включает дочерний контроллер. Это означает, что родительский контроллер будет выполнен до дочернего контроллера. Итак, первый setValue() будет определен, а затем элемент управления перейдет к дочернему контроллеру. $scope.variable будет назначен как "дочерний". Затем этот дочерний объект будет передан как аргумент функции родительского контроллера, где $scope.assign получит значение как "дочерний"
<!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>
Ответ 6
Я не уверен, должен ли вам "получить" доступ к дочерней сфере от родителя, но это возможно. Я знаю это, потому что я сделал это сам. Вот мой сценарий:
У меня есть функция, которая перемещает мои страницы путем изменения строки внутри переменной. Эта переменная указана в основном файле index.html как ng-include. Итак, когда строка изменяется, в этот ng-include загружается новый html файл. Внутри одного из этих html файлов у меня есть еще один ng-include. Подумайте об этом как о маленьком окне в первом окне. Каждый раз, когда я изменяю содержимое в этих окнах, я также меняю содержимое боковой панели. Эта боковая панель находится на родительском уровне. Но, когда я перехожу в меньшее окно внутри родителя, на боковой панели этого родительского уровня есть навигационные ссылки, которые меняют вещи в маленьком окне. Поскольку боковая панель находится на родительском уровне, а навигация для меньшего окна позаботится в своем собственном контроллере на уровне дочернего уровня, когда я нажимаю ссылки на боковой панели, он должен редактировать дочерний контроллер. Это может быть плохое программирование. Честно говоря, я не знаю. Я только начал с angularjs несколько месяцев назад, и я все еще учусь. Но для того, чтобы он работал для моего сценария, я создал функцию в родительской области, которая вызывается при загрузке детской области:
function parent($scope, service) {
setCurrentChildController = function (childScope) {
this.$scope.childScope = childScope;
}
}
function child($scope) {
scope.$parent.setCurrentChildController($scope);
}
Таким образом, теперь переменная родительской области $scope.childScope по существу является областью детского контроллера. Он имеет доступ ко всем переменным и функциям в пределах дочернего объекта. Если это плохое программирование, и каждый может придумать альтернативное решение проблемы с моим сценарием, это было бы здорово. Но это работает при необходимости.