элемент массива angular не обновляется при изменении области видимости

Потратил на это несколько часов, просмотрел многочисленные сообщения стека и блоги, но, похоже, не может получить это, чтобы обновить мою модель. В частности, я пытаюсь обновить элемент массива (ng-repeat). В приведенном ниже простом случае я перебираю список мест и, нажимая кнопку «Нравится», соответствующим образом обновляю сервер и отражаю изменения в элементе мест проведения в $scope.

в моем search.html есть директива:

<ion-content>
   <venues-list venues="venues"></venues-list>
</ion-content>

и контроллер поиска у меня есть:

app.controller('bleh', function(Service) {
   ...
   $scope.venues = [{ id: 1, name: 'Venue1', like: false },{ id: 2, name: 'Venue2', like: false }];
   ...
});

Там нет ничего необычного. Затем в моей директиве списка мест проведения:

app.directive('venues-list', function() {

   function venueListController($scope, Service) {

      $scope.likeToggle = function(venue, $index) {
            Service.likeVenue(venue.id, !venue.like).then(function() {
               $scope.venues[$index].like= !venue.like;
            });
      }
   }

   return {
      strict: 'E',
      templateUrl: 'venue.html',
      controller: venueListController,
      scope: {
         venues: '='
      }
   }
});

то в моем venue.html у меня есть:

<div ng-repeat="venue in venues">
  <p>{{venue.name}}</p>
  <button ng-click="likeToggle(venue, $index)">Like</button>
</div>

Я пробовал много разных вариантов:

$scope.$apply() // after updating the $scope or updating scope within apply's callback function;
$scope.$digest()
$timeout(function() { // $scope.venues[$index] .... }, 0);
safe(s,f){(s.$$phase||s.$root.$$phase)?f():s.$apply(f);}

so

safe($scope, function() { $scope.venues[$index].like = !venue.like });

Я еще не использовал ссылку в директиве, но мой шаблон places.html, очевидно, немного сложнее, чем представленный здесь.

ИЗМЕНИТЬ:

Просто чтобы обсуждение было актуальным, возможно, я должен был упомянуть: данные возвращаются с сервера без проблем, я обрабатываю ошибки и определенно попадаю в ту часть кода, где нужно обновить $scope. ПРИМЕЧАНИЕ: приведенный выше код является небольшим представлением полного приложения, но все основные части изложены выше.

  1. Контроллер поиска
  2. Сервис
  3. директива списка мест проведения и шаблон места проведения.html для сопровождения директивы
  4. директивный контроллер

РЕДАКТИРОВАНИЕ №2

$scope.foo = function() {
   $scope.venues[0].like = !$scope.venues[0].like;
}

Чтобы сделать это еще проще, приведенное выше не работает - так что на самом деле суть в том, что мои элементы в массиве не отражают обновления...

ИЗМЕНИТЬ №3

$scope.foo = function() {
   $scope.venues[0].like = !$scope.venues[0].like;
}

Приношу извинения - просто повторю то, что я пытался сказать выше - вышеизложенное меняет область действия, однако изменения не отражаются на представлении.


person Sash    schedule 09.06.2016    source источник
comment
Вы пробовали заказать «orderBy» на месте проведения.лайк? нет необходимости запускать круг $digest, вы привязали места проведения к $scope.   -  person Itsik Mauyhas    schedule 09.06.2016
comment
также можете опубликовать скрипку?   -  person Itsik Mauyhas    schedule 09.06.2016
comment
app.module('bleh', function(Service) { модуль? это controller?   -  person vp_arth    schedule 09.06.2016
comment
vp_arth: простите мой косяк, да контроллер - невнимательно смотрел.   -  person Sash    schedule 09.06.2016
comment
Ицик: Я постараюсь найти время, чтобы сделать быструю скрипку. Я пробовал, не запуская цикл $digest - насколько я понимаю, ng-click делает это внутри (может быть исправлено). ... даже выражение, например ‹div›{{venue.like}}‹/div›, всегда остается в одном и том же состоянии даже после попытки переключения и обновления контроллера формы.   -  person Sash    schedule 09.06.2016


Ответы (2)


Возможно, проблема связана с вашим сервисом и разрешением обещания. Можете ли вы поместить туда console.log и посмотреть, нормально ли работает разрешение обещания? или Можете ли вы поделиться этим битом кода. Кроме того, где вы проверяете обновление области? в рамках директивы или за ее пределами

person Viral Shah    schedule 09.06.2016
comment
Согласовано. Глядя на код, я вижу, что у вас нет обработчика ошибок для вызова службы. Если вы столкнетесь с ошибкой там, вы никогда ее не увидите, и это может объяснить ошибку, которую вы видите. - person Maurice Reeves; 09.06.2016
comment
insanevirus: сервисные вызовы работают, как и ожидалось, и возвращают успешное обновление БД... так что я определенно попадаю в $scope.venues[$index].like= !venue.like; ... как я уже сказал, все в приложении работает нормально, за исключением обновления отдельных элементов .... даже если я обновляю (и повторно загружаю с сервера), это будет отражать изменение соответствующим образом ... но, очевидно, я не хочу лезть на сервер каждый раз, когда нажимаю лайк :) - person Sash; 09.06.2016
comment
Морис Ривз: Я обрабатываю ошибки в своем приложении, как я уже упоминал, это просто немного упрощенное представление. включены только соответствующие биты - person Sash; 09.06.2016
comment
Сервисный вызов @Sash может работать нормально. Но после получения ответа об успешном выполнении могут возникнуть проблемы с разрешением обещания. В случае чего тогда не позвонят никогда. Так что просто поместите предупреждение или комментарий внутри then там, чтобы убедиться, что он действительно вызывается. - person Viral Shah; 09.06.2016
comment
Уфф, ладно. Область действия не обновляется внутри/вне директивы или в обоих местах? - person Viral Shah; 09.06.2016
comment
insanevirus: только что сделал это... он работает, как и ожидалось. p.s. Раньше я получал ошибки, когда пробовал $apply и $digest, что цикл $digest уже выполнялся. - person Sash; 09.06.2016
comment
insanevirus: область действия не обновляется внутри контроллера директив. (взгляните на директиву списка мест проведения и шаблон места проведения.html выше) - person Sash; 09.06.2016
comment
лол, я только что понял, что я не использую @ ‹name› :), чтобы обращаться к каждому из вас должным образом - person Sash; 09.06.2016
comment
@Саш, без проблем. Но опять же, вы говорите, что служба работает, как и ожидалось, но тогда ей звонят, вот что я прошу вас проверить. Извините за настойчивость, но иногда это все глупые вопросы! :) - person Viral Shah; 09.06.2016
comment
@insanevirus тогда называют да. - person Sash; 09.06.2016
comment
Ok. Я сомневаюсь, что это угловая проблема. Есть ли вероятность, что вы случайно обновляете подобную переменную дважды где-то в своем коде. Заставить его вернуться к исходному значению? Этот фиктивный код выглядит нормально, но, как вы сказали, исходный код немного сложнее. - person Viral Shah; 09.06.2016
comment
@Sash, пока вы нашли способ обойти это, реальная проблема все еще остается неясной. Ничего плохого с точки зрения angular. Кроме того, если у вас есть свободное время, пожалуйста, сделайте plunkr, чтобы мы могли попытаться решить и оригинал :) - person Viral Shah; 09.06.2016

ОК, после некоторого рефакторинга я наконец заработал.

«Исправление» (если вы хотите так назвать) моей конкретной проблемы было:

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

так, вместо:

<ion-content>
   <venues-list venues="venues"></venues-list>
</ion-content>

Теперь у меня есть:

<ion-content>
   <venues-list ng-repeat="venue in venues" venue="venue"></venues-list>
</ion-content>

и моя директива теперь выглядит так:

app.directive('venues-list', function() {

   function venueController($scope, Service) {

      $scope.likeToggle = function(venue) {
            Service.likeVenue(venue.id, !venue.like).then(function() {
               $scope.venue.like = !venue.like;
            });
      }
   }

   return {
      strict: 'E',
      templateUrl: 'venue.html',
      controller: venueController,
      scope: {
         venue: '='
      }
   }
});

Это помогло!

person Sash    schedule 09.06.2016