Оновіть змінну області батьківської області в 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

Чи можете ви опублікувати свій код? Це працює в скрипковому демо. Якщо у вашому контролі календаря використовується ізоляційна область, він не буде успадковано від батьківської області, тому вам потрібно буде передати значення в область директиви.
День

Вибачте, що забув про це питання. Я прийняв це, тому що зрештою мені вдалося змусити його працювати за допомогою цієї відповіді.
Malcr001

Я розумію, що введення {{parentobj.parentproperty}} в елемент ctrlParent div - це те, що декларує батьківський об'єкт і встановлює цей об'єкт як область 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
Гарне рішення! це працює, тому що коли чогось не знайдено у поточному діапазоні $, Angular шукає в $ батьківському. docs.angularjs.org/guide/scope (див. "Ієрархії сфери застосування").
Ело

Мені подобається ця відповідь, немає необхідності створювати зайвий об’єкт.
grimmdude

3
Майбутні читачі: Усі ці високі п’ять коментарів трохи помилкові. Створення двох функцій сеттера (які є "непотрібними об'єктами") для кожної змінної є незграбним і непотрібним хизуванням успадкування і не є кутовим способом. Місько Хевери, творець Angular, виступає з розмовою, в якій він навчає: "Кожен раз, коли у вас є ng-модель, десь має бути крапка. Якщо у вас немає точки, ви робите це неправильно". Мисько відео @ 29:19
Dan

як я можу застосувати це рішення за допомогою синтаксису controllerAS?
ніран

6

Це також працює (але не впевнений, чи це слід найкращої практики чи ні)

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

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

1
Ви правильно, використовуючи $ range. $ Parent.value буде працювати в більшості випадків, проте зазвичай це не найкраща ідея широко використовувати, оскільки це може бути важко керувати у великих, складніших проектах.
Алекс Джонсон

4

Якщо ви присвоюєте примітивний атрибут області, він завжди локальний для області застосування (можливо, створеної на льоту), навіть якщо батьківський діапазон має атрибут з тим самим іменем. Це дизайнерське рішення і хороше ІМХО.

Якщо вам потрібно змінити деякі примітиви (ints, booleans, strings) у батьківській області, з цього виду, вам потрібно, щоб він був атрибутом іншого об'єкта в цьому діапазоні, щоб призначення може прочитати:

<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.