I have a simple app using Onsen UI and am taking advantage of the carousel and updating the data based on whether the user swipes left or right to the current carousel element. Once they have swiped, I would like to remove that element from the carousel so that they can't get to it again. I am trying to use the postchange event which seems to work fine but when I call carousel.refresh() the carousel doesn't update.
The carousel is defined like this in the html:
<ons-carousel var="carousel" swipeable overscrollable auto-scroll fullscreen initial-index="1">
<ons-carousel-item ng-repeat="foo in bar.baz">
....
</ons-carousel-item>
</ons-carousel>
Because the carousel is initialized on a page other than the first, I've added an event handler to watch for a new page being pushed onto the navigation controller, and if it is the page with the carousel on it, then initialize a handler for the carousel's postchange event and update some things. I've simplified it for the case of this example.
ons.ready(function(){
mainNavigator.on('postpush', function(event){
var page = event.enterPage;
if (page.name == "carousel_page.html"){
carousel.on('postchange', function(event){
$scope.bar.baz.splice(event.lastActiveIndex, 1);
setImmediate(function(){
// even setting the array to [] here does not make a difference
carousel.refresh();
});
});
}
});
});
Stepping through everything I can verify that the array behind the carousel is updated correctly and the carousel variable is defined ok, and that the refresh() gets called, but my carousel never updates. What am I missing here?
I am using Angular with Onsen, is this somehow because of the way I'm adding the event handler? Is it outside of the $digest cycle or something?
There is a list of bugs here... ons-carousel was released in the last version of OnsenUI and it was only tested to be used with a static number of elements and some other features, but not in this way. Everything will be fixed in the next version in few weeks.
If you still want to try something, this could give you some ideas:
$scope.carousel.on('postchange', function(event){
$scope.$apply(function() {
$scope.bar.baz.splice(event.lastActiveIndex, 1);
});
setImmediate(function(){
carousel.refresh();
});
});
It should delete and refresh now, but due to some buggy behaviour the slideDistance may be wrong. To fix this you could think in using
$scope.carousel.setActiveCarouselItemIndex($scope.carousel.getActiveCarouselItemIndex());
right after carousel.refresh();
, but that would trigger again 'postchange' event...
To avoid this 'postchange' event problem you can do it a bit more angular-like:
// Let's do something when the ActiveCarouselItemIndex changes
$scope.$watch(function(){return $scope.carousel.getActiveCarouselItemIndex()}, function(newIndex,oldIndex){
if (newIndex !== oldIndex) {
$scope.bar.baz.splice(oldIndex, 1);
setImmediate(function(){
$scope.carousel.refresh();
// Avoid the position problem
$scope.carousel.setActiveCarouselItemIndex($scope.carousel.getActiveCarouselItemIndex());
});
}
});
// Still necessary
$scope.carousel.on('postchange', function(event){
$scope.$apply();
return;
});
This looks better than the previous one, but still is a bit buggy... you may find a way to modify it and solve the problems, but it is probably easier to wait for the next version where it will take care of dynamic carousels.
Hope it helps!