I'm using Bootstrap to display a carousel on my website, and I display several items per slide following this example . Using static images works perfectly well and I'm very happy about the results (example on this jsFiddle , make sure the display frame is big enough to avoid a strange effect due to boostrap's media queries, which I will take care of later ).
However now, I would like to define the content of the carousel from a variable and bind it with AngularJS with a ng-repeat
. That's where a problem occurs. The data is binded properly, but only the image considered as the "active" item displays. I understand that it makes sense, but it wasn't behaving like that with statically defined images. See this jsFiddle to see my bug.
What I tried so far :
HTML
<div class="carousel-started-themes" style="height:150px; width:700px;">
<div class="carousel slide" id="myCarousel">
<div class="carousel-inner">
<div class="item" ng-class="{active:!$index}" ng-repeat="img in image">
<div class="col-md-4"><a href="#"><img ng-src="{{img}}" class="img-responsive"></a>
</div>
</div>
</div>
<a class="left carousel-control" href="#myCarousel" data-slide="prev" style="z-index:10000;"><i class="glyphicon glyphicon-chevron-left"></i></a>
<a class="right carousel-control" href="#myCarousel" data-slide="next" style="z-index:10000;"><i class="glyphicon glyphicon-chevron-right"></i></a>
</div>
</div>
JS
function MyCtrl($scope) {
$scope.image =["https://wallpaperscraft.com/image/minimalism_sky_clouds_sun_mountains_lake_landscape_95458_1600x900.jpg", "https://wallpaperscraft.com/image/clouds_milky_way_eclipse_light_68883_1600x900.jpg", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSl5bsNT-Qtm0tfbydXFMuFCG27Kug6D5Z3hrgitIQqQq22Da95Ig", "https://wallpaper.wiki/wp-content/uploads/2017/05/Photos-1600x900-Wallpapers-HD.jpg", "https://wallpaperscraft.com/image/torzhok_tver_region_evening_sunset_river_reflection_autumn_russia_58028_1600x900.jpg", "https://wallpaper.wiki/wp-content/uploads/2017/04/wallpaper.wiki-1600x900-HD-Image-PIC-WPD0014727.jpg"];
}
$('#myCarousel').carousel({
interval: false
});
$('.carousel .item').each(function() {
var next = $(this).next();
if (!next.length) {
next = $(this).siblings(':first');
}
next.children(':first-child').clone().appendTo($(this));
if (next.next().length > 0) {
next.next().children(':first-child').clone().appendTo($(this));
} else {
$(this).siblings(':first').children(':first-child').clone().appendTo($(this));
}
});
Why do you need to show/hide at all? perhaps you could just use overflow:hidden; and and just use jquery to scroll left and right without a scroll bar. That way, there would never be a hide condition.
I found the solution.
The problem was that jQuery was executing too fast, not waiting for ng-repeat to be finished before binding the data and adding the elements for multiple display.
I used the following callback directive to solve the problem, and called the jQuery methods inside the callback function.
The directive:
app.directive("repeatEnd", function(){
return {
restrict: "A",
link: function (scope, element, attrs) {
if (scope.$last) {
scope.$eval(attrs.repeatEnd);
}
}
};
});
This doesn't solve everything. There is still a problem with Angular binding not being applied since the elements are binded after the repeat is over. To work around this problem, I changed the jQuery code to get the index of the current element in the ng-repeat, and call my data from the index:
$scope.repeatOver = function(){
$('#myCarousel').carousel({
interval: false
});
$('.carousel .item').each(function(index){
var next = $(this).next();
var indexNext = index+1;
var indexNextNext = index+2;
if (!next.length) {
next = $(this).siblings(':first');
indexNext = 0;
indexNextNext = 1;
}
next.children(':first-child').clone().appendTo($(this));
// Change the source of the element
$(this).children(':first-child').next()[0].getElementsByTagName('img')[0].src = $scope.image[indexNext];
if (next.next().length>0) {
next.next().children(':first-child').clone().appendTo($(this));
// Change the source of the element
$(this).children(':first-child').next().next()[0].getElementsByTagName('img')[0].src = $scope.image[indexNextNext];
}
else {
indexNextNext = 0;
$(this).siblings(':first').children(':first-child').clone().appendTo($(this));
// Change the source of the element
$(this).children(':first-child').next().next()[0].getElementsByTagName('img')[0].src = $scope.image[indexNextNext];
}
});
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.