$scope обновляется в представлении, а не в контроллере для angularJs

У меня есть область, определенная в контроллере, как указано ниже:

Контроллер:

var app = angular.module('app', ['ui.select2']);

app.controller('MyCtrl',
  [
    '$scope',
    '$q',
    '$timeout',
    function ($scope, $, $timeout) {
      $scope.data = {};
       $scope.countries = [{
          name : 'India', code : 'IA'
        }, {
          name : 'Israel', code : 'IS'
        }];

        $scope.selectedCountries = [
          'IA'
        ];

        $scope.$watch('selectedCountries', function(newValue, oldValue) {
           console.log ('data');
    });
]);

вид выглядит так:

<select
        ui-select2
        multiple
        ng-model="selectedCountries"
        data-placeholder="Choose or Search for countries"
        name="countries"
        style="width:200px;">
        <option ng-repeat="country in countries" value="{{country.code}}">{{country.name}}</option>
</select>

Теперь, когда значение изменяется в контроллере с помощью раскрывающегося списка выбора, изменения значения отражаются в представлении. Но часы так и не вызываются, так как прицел не меняется. Любая идея, почему область не обновляется?


person insomiac    schedule 25.08.2013    source источник
comment
вид можешь показать?   -  person Davin Tryon    schedule 25.08.2013
comment
Вопросы, касающиеся проблем с написанным вами кодом, должны описывать конкретную проблему — и включать действительный код для ее воспроизведения — в самом вопросе.   -  person Stewie    schedule 25.08.2013
comment
Это может быть связано с тем, что представление фактически не касается переменной $scope.selectedCountries. Не могли бы вы показать нам полный код для отслеживания проблемы?   -  person NicoArbogast    schedule 25.08.2013
comment
Я использую плагин select2 angular js, он отражает изменения в представлении, но не в контроллере.   -  person insomiac    schedule 26.08.2013
comment
обновил мой код, надеюсь поможет..   -  person insomiac    schedule 26.08.2013


Ответы (1)


Для просмотра коллекций передайте true в качестве третьего параметра в $watch, так что он станет таким:

$scope.$watch('selectedCountries', function(...) {...}, true);

Это заставляет $digest рекурсивно проходить через коллекцию, а не просто проверять ссылки.

В качестве альтернативы, если у вас есть глубокая структура, и вам нужно знать только, изменился ли нижний уровень (то есть добавлены или удалены элементы), вы можете использовать $watchCollection вместо $watch.

ОБНОВЛЕНИЕ: Рабочий плункер (работает без глубокого $watch()): http://www.plnkr.co/edit/VaWBq9?p=preview

person Jussi Kosunen    schedule 25.08.2013
comment
$watchCollection() действует как $watch('...', function() { ...}, true) — другими словами, она выполняет поверхностное сравнение: для массивов это означает просмотр элементов массива, для карт объектов это означает просмотр свойств. Неглубокое сравнение обнаружит, были ли элементы добавлены или удалены, но также обнаружит, изменились ли значения каких-либо элементов. Вот плункер, показывающий последний. - person Mark Rajcok; 26.08.2013
comment
@insomiac Кажется, select:multiple каждый раз заменяет массив, а не объединяет его, поэтому он работает без глубокого $watch: plnkr.co/edit/VaWBq9?p=preview Похоже, ваш код здесь работает нормально. @MarkRajcok $watchCollection(..) неглубокий, а $watch(.., .., true) глубокий. Оба увидят, изменилось ли содержимое объекта или массива, но только последний увидит, изменилось ли содержимое внутри этого содержимого. - person Jussi Kosunen; 27.08.2013