Create multiple sliders with knockout

1,057 views
Skip to first unread message

Jens Hoffmann

unread,
Jan 20, 2014, 12:50:05 PM1/20/14
to knock...@googlegroups.com
Hi, 

i am trying to use a slider in combination with knockout.
The pagination just doesn't work. Because the slider is initalized on every ajax complete (see java script code at the bottom). 
Does anyone has a solution for that issue? Thank you very much in advance. 


1)
<div class="swiper-container">
<div class="swiper-wrapper">
<pre  class="r space p-ls p-rs no-mt" data-bind="text: Pictures().length"> </pre>
<!-- ko foreach: Pic.List -->
<div class="swiper-slide"> 
<img data-bind="attr:{src: Image.imageUrl}" />
</div>
<!-- /ko -->
<!-- ko foreach: Pic.List --> Second foreach is needed for the pagination!
        

                        Initalize each Container!
                        I would have to recreate the slider every time the data changes. 

<!-- /ko -->
</div>
</div>



Here is the java script code I am using right now. 

// This is called every time the ajax is completed. 
// I would have to somehow combine it with knockout

2)
<script type="text/javascript">           
 
$(document).ajaxComplete(function() { // this is necessary but takes a long time to load!
jQuery(function($) { initializeContainers(); });
function initializeContainers() {
$('.swiper-container').each(function () {
var config = {
 mode: 'horizontal',
 calculateHeight: true,
 loop: true,
 initialSlide: 0,
 visibilityFullFit: true
};
if ($(this).find('.swiper-wrapper').children().length > 1) {
if ($(this).find('.pagination').length < 1)
{      
var $pager = $('<div class="pagination" />').appendTo(this);
config.pagination = $pager[0];
config.paginationClickable = true;
console.log($(this).find('.pagination').length);
}
}
var swiper = $(this).swiper(config);  // Create the slider!
 
$('.arrow-left').on('click', function (e) {
e.preventDefault();
swiper.swipePrev();
});
$('.arrow-right').on('click', function (e) {
e.preventDefault();
swiper.swipeNext();
});
});
}
});       
</script>

Jens Hoffmann

unread,
Jan 20, 2014, 1:04:47 PM1/20/14
to knock...@googlegroups.com
Hey guy,

I think i found a kind of dirty solution. 
Is there a better way in knockout with bindings?

  if ($(this).find('.pagination').length < 1)
  {      
...
  var swiper = $(this).swiper(config);
  }
 

Winston Fassett

unread,
Jan 21, 2014, 6:25:12 PM1/21/14
to knock...@googlegroups.com
Coincidentally, I've been looking into the same slider and working through some similar problems.  

You might be able to adapt this binding to your needs.  The code is one day old and I'm still noodling on it, but you might find it useful:  http://jsbin.com/IrOjEQUL/2/edit

It's been challenging to figure out when to create and update the slider instance with respect to the KO native template lifecycle.  Initially I attached to the afterRender callback of the swiper-container element, but then I needed a way to update the slider when slides were added/removed.  Attaching to the afterRender callback of the foreach binding fired a separate call for each element inserted, which was too many updates -- I only wanted to update the slider (by calling slider.reInit()) when KO was done rendering my foreach, rather than after KO had rendered each element, and I couldn't find any hook for that.  Please, someone let me know if I am missing something obvious here.

In the absence of such a hook, I wrote a binding that uses a uses a throttledObservable to effectively debounce the afterRender and beforeRemove events of the template / foreach binding.

Not sure if this is the best way to do it, but it seems to be working ok.  

Jens Hoffmann

unread,
Jan 23, 2014, 4:05:23 AM1/23/14
to knock...@googlegroups.com
Hello Winston,

thank you very much for sharing your code. I will try it out as soon as possible. 

jens. 

Jens Hoffmann

unread,
Jan 24, 2014, 5:03:33 AM1/24/14
to knock...@googlegroups.com
Hi,

now I am facing the problem that the page is rendered to slow. 
I have about 50 sliders. And each slider has 5 or more pictures inside. 
Is there a way to just render one picture, so that the user sees something till the other pictures are loaded. 

I found some articles about lazy loading observables: 

May be that would be a solution.

greetings jens

Jens Hoffmann

unread,
Jan 24, 2014, 10:31:10 AM1/24/14
to knock...@googlegroups.com

Winston Fassett

unread,
Jan 24, 2014, 11:13:27 AM1/24/14
to knock...@googlegroups.com
My first thought was, "wow that's a lot of sliders".  But then I tweaked the JSBin code to add a performance test.  It seems to work pretty well.  On my machine it's rendering 50 sliders in < 200ms.  


In any case, if your rendering is too slow, those are some good options.  I haven't used thinkloop's libraries, but they look like a good bet.  He also has a progressive filtering library that might be worth checking out because of how it renders "minimally blocking chunks of data at a time", i.e. you could render 5 sliders at a time and get your page to initially render more quickly while the remaining sliders continue to get rendered.





--
You received this message because you are subscribed to a topic in the Google Groups "KnockoutJS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/knockoutjs/TeAodPIxjlg/unsubscribe.
To unsubscribe from this group and all its topics, send an email to knockoutjs+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Jens Hoffmann

unread,
Jan 28, 2014, 11:51:23 AM1/28/14
to knock...@googlegroups.com
Thank you very much for the hint. The progressive filter works like a charm. 
Your slider code also. 
Reply all
Reply to author
Forward
0 new messages