I have created a simple content rotator using the excellent Cycle.js plugin, this gets it’s content from my Knockout.JS view model property (appViewModel.mediaPlayer in this case):
e.g.
var testData = [{ url: "media/1.png" }, { url: "media/2.jpg"}];
var appViewModel =
{
mediaPlayer: new ko.observableArray(testData)
};
ko.applyBindings(appViewModel);
This is rendered in the view using JQuery Tmpl e.g.
<script id="mediaPlayerTemplate" type="text/template">
<img src=${url} />
</script>
<div class="adContainer" data-bind="template: {name: 'mediaPlayerTemplate', foreach: mediaPlayer}">
</div>
To start the image transition I simply call the Cycle plugins method “cycle”:
$('.adContainer').cycle({
fx: 'fade',
timeout: 1000,
speed: 500
});
This works great, however when I update my view model media player content the cycle plugin stops working…this is not a problem as a simple call to cycle() will start it again.
However, my question is, where is the best place to make the call to cycle() to update the view? I figured I could subscribe to the mediaPlayer changes, simply calling the method when required however this would mean that I have to put the JQuery element/view logic in the View Model which feels wrong (perhaps I’m trying to be too purist!).
In short, how do I trigger functions in the view from the view model without the view model knowing about the views function? In Silverlight/WPF this was possible with triggers in XAML but I’m not sure how to achieve the same separation using Knockout.JS
I think it is better to do this using bindinghandlers, this will also allow you properly dispose plugin when content is re-rendered.
Your example (it will change cycle after 5 seconds):
http://jsfiddle.net/nickolsky/uXDUA/2/
HTML:
JAVASCRIPT: