Reputation: 81617
Here is the situation: I have a panel that contains a limited list of elements. I have implemented some sort of slider on it: when I click on a button, this panel moves to the left, and get back with the list of updated items (i.e. the items present on the next page).
My code looks like that:
<div id="slider" class="row">
<span ng-repeat="d in data | startFrom: (page * pagination) | limitTo: pagination" class="col-lg-4 box" >{{ d }}</span>
</div>
<button id="ko" type="button" class="btn btn-danger" ng-click="nextPageAndAnimate();">Next page ({{ page }})</button>
<button id="ok" type="button" class="btn btn-success" ng-click="nextPage();">Next page ({{ page }})</button>
on the Angular Controller side:
myApp.controller('MainCtrl', function($scope) {
$scope.data = 'abcdefghijklmnopqrstuvwxyz'.split('');
$scope.page = 0;
$scope.pagination = 5;
// Without animation, works correctly.
$scope.nextPage = function() {
$scope.page = $scope.page + 1;
};
// Use animation, not working correctly.
$scope.nextPageAndAnimate = function() {
console.log('Start animation');
$('#slider').animate({ left: '-200px' }, 1000, function() {
$scope.page = $scope.page + 1;
console.log('Page updated');
$(this).animate({ left: '0' }, 1000, function() {
console.log('End of animation');
});
});
};
});
You have the full example on this Plunker.
My idea was the following: I start the animation to hide the #slider
. At the middle of the animation, I update the $scope.page
model to ask Angular to display the next 5 elements of my list. Finally, I start a new animation to show the #slider
again.
When using the button#ok
, I "simply" update the $scope.page
model value, so the pagination works correctly, but without animation.
If I use the button#ko
, the update of the $scope.page
model does not work correctly, but I have animation: on the first click, the box animtes but displays the same elements (i.e. $scope.page
is still equals to 0
). When I click a second time on the button, before the animation, the elements are updated ($scope.page
is equal to 1
), but at the end, I get the same elements.
I'm not sure to understand why the model is not updated at the correct moment, but I suspect that it's because the update is made in the jQuery animate
callback, no?
How to solve my problem?
Upvotes: 0
Views: 518
Reputation: 12404
Have you called scope.$apply()
whenever you update the page in the animation? Angular is smart when binding click events to controller functions, automatically checking for scope changes when they have been executed.
In your animation however, the scope update does not happen until a few milliseconds after the click event has been triggered. There is no way for angular to tell that the scope has been updated. This is the reason scope.$apply()
exists.
See also: https://github.com/angular/angular.js/wiki/When-to-use-$scope.$apply()
Upvotes: 2