I am trying to create a dynamic carousel with data coming from an observable knockout array.
There are several problems with the result.
The carousel is not displayed at all, instead all the owl elements have an active class and are displayed on the page.
Another problem is that none of the dots or buttons are displayed.
What I'm trying to do is add or remove items to myItems collection and automatically update the carousel in the user interface
I am using knockout 3.3, base zurb 5, jQuery 2.1.4
custom knockout handler
(function (factory) {
if (typeof define === "function" && define.amd) {
define(["knockout", "jquery", "jquery.ui.sortable"], factory);
} else {
factory(window.ko, jQuery);
}
})(function (ko, $, undefined) {
var refreshOwl = function (owl) {
owl.$owlItems = owl.$stage.children(".owl-item");
owl.$userItems = owl.$owlItems.children();
owl.itemsAmount = owl.$userItems.length;
owl.refresh();
};
var makeTemplateBindingOptions = function (options, afterRender) {
var templateOptions = {
foreach: options.data,
as: options.as,
afterRender: afterRender,
afterAdd: options.afterAdd,
beforeRemove: options.beforeRemove
};
if (options.afterRender) {
var userAfterRender = options.afterRender;
templateOptions.afterRender = function (element, data) {
if (afterRender) {
afterRender.call(data, element, data);
}
userAfterRender(data, element, data);
};
}
return templateOptions;
};
ko.bindingHandlers.owlCarousel = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var options = ko.utils.unwrapObservable(valueAccessor());
var $elem = $(element);
var owlOptions = options.owlOptions || {};
$elem.owlCarousel(owlOptions);
var owl = $elem.data("owl.carousel");
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
if (owl) {
owl.destroy();
}
});
var templateOptions = makeTemplateBindingOptions(options, function () {
refreshOwl(owl);
});
return ko.bindingHandlers.template.init(owl.$stage[0], function () { return templateOptions; }, allBindingsAccessor, viewModel, bindingContext);
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var options = ko.utils.unwrapObservable(valueAccessor());
var $elem = $(element);
var owl = $elem.data("owl.carousel");
var templateOptions = makeTemplateBindingOptions(options, function (element, data) {
refreshOwl(owl);
});
ko.bindingHandlers.template.update(owl.$stage[0], function () { return templateOptions; }, allBindingsAccessor, viewModel, bindingContext);
}
};
});
Javascript code for binding to view
var myItems = ko.observableArray([
{ name: 'Image 1', url: "http://placehold.it/150x200&text=book cover1" },
{ name: 'Image 2', url: "http://placehold.it/150x200&text=book cover2" },
{ name: 'Image 3', url: "http://placehold.it/150x200&text=book cover3" },
{ name: 'Image 4', url: "http://placehold.it/150x200&text=book cover4" },
{ name: 'Image 5', url: "http://placehold.it/150x200&text=book cover5" },
{ name: 'Image 6', url: "http://placehold.it/150x200&text=book cover6" },
{ name: 'Image 7', url: "http://placehold.it/150x200&text=book cover7" },
{ name: 'Image 8', url: "http://placehold.it/150x200&text=book cover8" }
]);
HTML:
<div id="myCarousel"
class="owl-carousel owl-theme book-slide large-11 large-centered columns"
data-bind="owlCarousel: { data: myItems, owlOptions: { items: 3 } }">
<img data-bind="attr: { src: url, title: name, alt: name }" />
</div>
HTML output:
<div class="owl-carousel owl-theme book-slide large-11 large-centered columns owl-loaded owl-drag" id="myCarousel" data-bind="owlCarousel: { data: myItems, owlOptions: { responsive:{ 0:{ items:2}, 600:{items:3}, 1000:{items:5}} } }">
<div class="owl-stage-outer">
<div class="owl-stage" style="transition:all; width: 1016px; transform: translate3d(0px, 0px, 0px);">
<div class="owl-item active" style="width: 203.2px;">
<img title="Image 1" alt="Image 1" src="http://placehold.it/150x200&text=book cover1" data-bind="attr: { src: url, title: name, alt: name }">
</div>
<div class="owl-item active" style="width: 203.2px;">
<img title="Image 2" alt="Image 2" src="http://placehold.it/150x200&text=book cover2" data-bind="attr: { src: url, title: name, alt: name }">
</div>
<div class="owl-item active" style="width: 203.2px;">
<img title="Image 3" alt="Image 3" src="http://placehold.it/150x200&text=book cover3" data-bind="attr: { src: url, title: name, alt: name }">
</div>
<div class="owl-item active" style="width: 203.2px;">
<img title="Image 4" alt="Image 4" src="http://placehold.it/150x200&text=book cover4" data-bind="attr: { src: url, title: name, alt: name }">
</div>
<div class="owl-item active" style="width: 203.2px;">
<img title="Image 5" alt="Image 5" src="http://placehold.it/150x200&text=book cover5" data-bind="attr: { src: url, title: name, alt: name }">
</div>
<div class="owl-item active" style="width: 203.2px;">
<img title="Image 6" alt="Image 6" src="http://placehold.it/150x200&text=book cover6" data-bind="attr: { src: url, title: name, alt: name }">
</div>
<div class="owl-item active" style="width: 203.2px;">
<img title="Image 7" alt="Image 7" src="http://placehold.it/150x200&text=book cover7" data-bind="attr: { src: url, title: name, alt: name }">
</div>
<div class="owl-item active" style="width: 203.2px;">
<img title="Image 8" alt="Image 8" src="http://placehold.it/150x200&text=book cover8" data-bind="attr: { src: url, title: name, alt: name }">
</div>
</div>
</div>
<div class="owl-nav disabled">
<div class="owl-prev">prev</div>
<div class="owl-next">next</div>
</div>
<div class="owl-dots disabled">
<div class="owl-dot active">
<span></span>
</div>
</div>
Any ideas on what I'm doing wrong?