2

Spent a few hours on this already, sifted through numerous stack posts and blogs but can't seem to get this to make my model update. More specifically, I am trying to update an array item (ng-repeat). In the simple case below, I iterate over venues list, and upon toggling a "like" button, I update the server appropriately, and reflect the change on the venues item on the $scope.

in my search.html I have a directive:

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

and search controller I have:

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

Nothing unusual there. Then in my venues-list directive:

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: '='
      }
   }
});

then in my venue.html I have:

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

I have tried many different options:

$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 });

I haven't yet used the link within the directive, but my venues.html template is obviously a little more elaborate than presented here.

EDIT:

Just to keep the discussion relevant, perhaps I should have mentioned - the data is coming back from the server with no issues, I am handling errors and I am definitely hitting the portion of the code where the $scope is to be updated. NOTE: the above code is a small representation of the full app, but all the fundamental pieces are articulated above.

  1. Search Controller
  2. Venues Service
  3. venue-list directive and venue.html template to accompany the directive
  4. directive controller

EDIT #2

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

Just to keep it even simpler, the above doesn't work - so really, the bottom line is my items within an array are not reflecting the updates ...

EDIT #3

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

My apologies - just to re-iterate what I was trying to say above - the above is changing the scope, however, the changes are not being reflected on the view.

5
  • Did you try 'orderBy' on venue.like? there is no need to start a $digest circle, you have attched venues to $scope. Commented Jun 9, 2016 at 13:05
  • also can you post a fiddle? Commented Jun 9, 2016 at 13:05
  • 1
    app.module('bleh', function(Service) { module? is it controller? Commented Jun 9, 2016 at 13:07
  • vp_arth: sorry my bad, yes controller - I wasn't paying attention. Commented Jun 9, 2016 at 13:10
  • Itsik: I'll try and find time to do a quick fiddle. I tried without kicking off a $digest cycle - from what I understand ng-click does this internally (stand to be corrected). ... even an expression i.e. <div>{{venue.like}}</div> always stays the same state even after attempting to toggle and update form controller. Commented Jun 9, 2016 at 13:12

2 Answers 2

1

Perhaps the issue is with your service and promise resolution.. Can you put a console.log there and see if the promise resolution is working fine? or Can you share that code bit. Also where are you checking for scope update? within directive or outside

Sign up to request clarification or add additional context in comments.

12 Comments

Agreed. Looking at the code, I see you don't have an error handler put in place for the service call. If you are encountering an error there, you're never going to see it, and that could account for the bug you're seeing.
insanevirus: service calls are working as expected and returning a successful update of the DB ... so I am definitely hitting $scope.venues[$index].like= !venue.like; ... like I said, everything in the app works fine apart from the update of individual items.... even if i refresh (and re-fetch from the server), it will reflect the change appropriately ... but obviously I don't want to be hitting the server, every time I hit a "like" button :)
Maurice Reeves: I'm handling errors on my app, as I mentioned, this is just a slightly simplified representation. only included relevant bits
@Sash service call may be working fine. But after the success response is received, the promise resolution might be having issues. In which case then will not get called ever. So just put an alert or comment inside then there to ensure that it is getting called indeed
ohh ok. The scope is not getting updated inside/outside directive or both places ?
|
1

OK after some refactoring I finally got it working.

The "fix" (if you want to call it that) to my specific problem was:

instead of passing an array of venues, I was iterating over the array on the parent controller, passing in a venue as an element attribute that would bind (two-way) on the isolated scope of the directive.

so, instead of:

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

I now have:

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

and my directive now looks like:

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: '='
      }
   }
});

This did the trick!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.