Reputation: 1638
I have a problem which I can't seem to get around.
I have a simple angular repeat setup to output some slides. There are different sets of slides which can be changed. I'm using a jQuery plugin for the slider which works great.
The problem is that when I run the jQuery slider plugin, it ofcourse changes the html structure. So when I change the slides in the controller scope, angular doesn't remove the old slides.
I have a working example here:
http://jsfiddle.net/antony_publica/ccvjz4au/
To test, scroll through the slides, there should be 1, 2 3, then 4. Click listing 2. Now when you scroll through you see slides 1 through 8. When it should have 5 through 8.
HTML
<div ng-controller="MyCtrl">
Listing Id: {{current_listing.id}}
<div class="image_slider col-md-9" ng-if="current_listing">
<div class="slide slick-slide" ng-repeat="slide in current_listing.slides" repeat-end="initSlider()" >
{{slide}}
</div>
</div>
<button ng-click="current_listing = listing">Listing 1</button>
<button ng-click="current_listing = listing2">Listing 2</button>
</div>
JS
var myApp = angular.module('myApp',[]);
myApp.directive("repeatEnd", function(){
return {
restrict: "A",
link: function (scope, element, attrs) {
if (scope.$last) {
setTimeout(function(){
scope.$eval(attrs.repeatEnd);
}, 50);
}
}
};
});
function MyCtrl($scope) {
$scope.listing = {
id: 1,
slides: ['Slide 1','Slide 2','Slide 3', 'Slide 4']
};
$scope.listing2 = {
id: 2,
slides: ['Slide 5','Slide 6','Slide 7', 'Slide 8']
};
$scope.current_listing =$scope.listing;
$scope.initSlider = function(){
if($('.image_slider').hasClass('slick-slider')){
$('.image_slider').slick('unslick');
}
$('.image_slider').slick();
}
}
Upvotes: 1
Views: 414
Reputation: 2191
I created a pagination script inside your directive that will show only the slides that are contained within your current_listing.slides
object property value. I removed the ng-repeat
directive from your html because it was adding four more slides to the dom each time you clicked on a listing button. I also moved your {{ scope variable here }}
code from your html and placed the variables inside of ng-bind
directives so that the brackets are not displayed on the screen before angular compiles. I also added an ng-click
directive to your listing buttons that pass an integer value to the controller that sets the current_listing
value.
Live Example: http://codepen.io/larryjoelane/pen/ZWzObo
HTML:
<div ng-app="myApp" ng-controller="MyCtrl">
Listing Id: <span ng-bind="current_listing.id"></span>
<div repeat-end class="image_slider col-md-9">
<div ng-bind="slides" class="slick">
</div>
</div>
<button ng-click="changeListing(1)">Listing 1</button>
<button ng-click="changeListing(2)">Listing 2</button>
</div>
Angular/JQuery:
(function($) {
var myApp = angular.module('myApp', []);
myApp.directive("repeatEnd", function($timeout) {
return {
restrict: "A",
link: function(scope, element, attrs) { //begin link
//let angular compile first then call the jquery code
$timeout(function() { //begin timeout
function buildSlides() {
//array to hold the slides
var slides = [];
//loop through and the opening and closing div tags to the slides
for (var i = 0; i < scope.current_listing.slides.length; i++) { //begin for
//add the slide
slides.push("<div>" + scope.current_listing.slides[i] + "</div>");
} //end for
//return the slides html
return slides.join("");
} //end function
//initalize slick slider
$(element).slick(scope.$eval());
//check for changes in the listing
scope.$watch('current_listing', function(newValue, oldValue) { //begin watch
//if there is a new value
if (newValue) {
//destroy the slick slider
$(element).slick("unslick");
//store the html
var content = buildSlides();
//populate the slides
scope.slides = scope.$eval(element.html(content));
//reinitalize slick slider
$(element).slick();
}
}); //end watch
}); //end timeout
} //end link
};
});
myApp.controller("MyCtrl", ["$scope", "$timeout", function($scope, $timeout) {
$scope.listing = {
id: 1,
slides: ['Slide 1', 'Slide 2', 'Slide 3', 'Slide 4']
};
$scope.listing2 = {
id: 2,
slides: ['Slide 5', 'Slide 6', 'Slide 7', 'Slide 8']
};
//intialize the listing
$scope.current_listing = $scope.listing;
//change the listing on click
$scope.changeListing = function(listNum) { //begin function
//Assign the listings based on the listNum
//passed in as a parameter.
if (listNum === 1) {
$scope.current_listing = $scope.listing;
} else if (listNum === 2) {
$scope.current_listing = $scope.listing2;
}
} //end function
}]);
})(jQuery);
Upvotes: 1