Обновить переменную родительской области в AngularJS


113

У меня есть два контроллера, один в другом. Теперь я знаю, что дочерняя область наследует свойства из родительской области, но есть ли способ обновить переменную родительской области? Пока очевидных решений не встречал.

В моей ситуации у меня есть контроллер календаря в форме. Я хотел бы обновить даты начала и окончания из родительской области (которая является формой), чтобы форма имела даты начала и окончания при отправке.


похоже, что ваш контроллер календаря должен быть директивой.
Иона

Ответы:


193

Вам нужно использовать объект (не примитив) в родительской области, и тогда вы сможете обновить его непосредственно из дочерней области

Родитель:

app.controller('ctrlParent',function($scope){
    $scope.parentprimitive = "someprimitive";
    $scope.parentobj = {};
    $scope.parentobj.parentproperty = "someproperty";
});

Ребенок:

app.controller('ctrlChild',function($scope){
    $scope.parentprimitive = "this will NOT modify the parent"; //new child scope variable
    $scope.parentobj.parentproperty = "this WILL modify the parent";
});

Рабочая демонстрация : http://jsfiddle.net/sh0ber/xxNxj/

См. Какие нюансы наследования прототипа / прототипа области видимости в AngularJS?


1
Я получаю эту ошибку, когда пытаюсь реализовать это: «Невозможно установить свойство« parentproperty »на undefined».
Malcr001 05

Вы можете разместить свой код? Он работает в демоверсии скрипки. Если ваш элемент управления календарем использует изолированную область видимости, он не будет наследоваться от родительской области, поэтому вам нужно будет передать значение в область действия директивы.
Дэн

Извините, я забыл об этом вопросе. Я принял его, потому что в конце концов мне удалось заставить его работать с помощью этого ответа.
Malcr001

Я понимаю, что размещение {{parentobj.parentproperty}} в элементе div ctrlParent - это то, что объявляет объект parentobj и устанавливает этот объект как находящийся в области ctrlParent. Это правильное предположение?
Стефан

1
Спасибо, работает! Я обязательно должен прочитать об этом (прототипное наследование и примитивы). Можете ли вы порекомендовать хорошее чтение, которое объясняет немного больше, чем ваша ссылка SO?
jvannistelrooy

116

Есть еще один способ выполнить эту задачу - не использовать $scope.$parentпеременную.

Просто подготовьте метод для изменения значения в родительской области и используйте его в дочерней. Как это:

app.controller('ctrlParent',function($scope) {
  $scope.simpleValue = 'x';
  $scope.changeSimpleValue = function(newVal) {
    $scope.simpleValue = newVal;
  };
});

app.controller('ctrlChild',function($scope){
    $scope.changeSimpleValue('y');
});

Это также работает и дает вам больше контроля над изменениями значений.

Вы можете также вызвать метод даже в HTML , как: <a ng-click="changeSimpleValue('y')" href="#">click me!</a>.


1
Хорошее решение! это работает, потому что, когда что-то не найдено в текущей $ scope, Angular ищет в $ parent. docs.angularjs.org/guide/scope (см. «Иерархии областей видимости »).
Эло

Мне нравится этот ответ, не нужно создавать лишний объект.
grimmdude

3
Будущие читатели: Все эти пять комментариев немного ошибочны. Создание двух функций-установщиков (которые являются «ненужными объектами») для каждой переменной - это неуклюжая и ненужная куча наследования, а не метод Angular. Миско Хевери, создатель Angular, выступает с докладом, в котором учит: «Всякий раз, когда у вас есть ng-модель, где-то должна быть точка. Если у вас нет точки, значит, вы делаете это неправильно». Misko video @ 29:19
Dan

как я могу применить это решение, используя синтаксис controllerAS?
niran

6

Это также работает (но не уверен, следует ли это передовой практике или нет)

app.controller('ctrlParent',function($scope) {
    $scope.simpleValue = 'x';
});

app.controller('ctrlChild',function($scope){
    $scope.$parent.simpleValue = 'y';
});

1
Вы правы, использование $ scope. $ Parent.value будет работать в большинстве случаев, однако обычно это не лучшая идея для широкого использования, так как им может быть трудно управлять в более крупных и более сложных проектах.
Alex Johnson

4

Когда вы назначаете примитивный атрибут области, он всегда является локальным по отношению к области (возможно, создается «на лету»), даже если родительская область имеет атрибут с тем же именем. Это дизайнерское решение, и ИМХО хорошее.

Если вам нужно изменить какой-то примитив (целые числа, логические значения, строки) в родительской области видимости, из представления вам нужно, чтобы он был атрибутом другого объекта в этой области, поэтому присвоение может выглядеть так:

<a ng-click="viewData.myAttr = 4">Click me!</a>

и он, в свою очередь:

  1. получить viewDataобъект из любой области, в которой он определен
  2. присвоить 4 его myAttrатрибуту.

4

Для доступа к переменным, объявленным в родительском элементе, мы должны использовать $ parent в дочернем контроллере или файле шаблона.

В контроллере

$scope.$parent.varaiable_name

В шаблоне html

ng-model="$parent.varaiable_name"
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.