I'm struggling to integrate a jquery-ui slider widget into my Meteor app. The idea is to have a slider value in a Mongo collection and the slider needs to be reactive (automatically synced between clients). I've achieved this and it works but the implementation is not very elegant and clean. It's quite hard to maintain, test and extend such code. I've achieved this via Tracker.autorun and jquery slider slide handle (_.throttle
is used to limit mongo update interval).
I'm new to Meteor, and it's awesome, but so far couldn't find better way to implement this (which I bet exists):
Slider = new Meteor.Collection("Slider");
if (Meteor.isClient) {
Template.slide.rendered = function() {
var handler = _.throttle(function(event, ui) {
var val = Slider.findOne({});
Slider.update({ _id: val._id }, {$set: {slide: ui.value}});
}, 50, { leading: false });
if (!this.$('#slider').data('uiSlider')) {
$("#slider").slider({
slide: handler
});
}
Tracker.autorun(function() {
var slider = Slider.findOne({});
if (slider) {
this.$('#slider').data('uiSlider').value(slider.slide);
}
});
};
}
//seed Collection
if (Meteor.isServer) {
if (Slider.find().count() == 0) {
Slider.insert({
slide: 20
});
}
}
HTML
<body>
<h1>jquery-ui slider test</h1>
{{> slide}}
</body>
<template name="slide">
<div id="slider"></div>
</template>
1 Answer 1
I think you can avoid the Tracker.autorun completely by updating the value in a template helper -- this is possible because your data is coming from a Collection, so it's already reactive. You can play around with it in this MeteorPad, but a brief summary follows:
<!--HTML-->
<template name="slider">
<div id="slider"></div>
Slider's current value is...{{sliderVal}}<!-- You could get rid of this and just do {{sliderVal}} and have that return nothing if you want no text-->
</template>
//JS -- ommitted the rendered bit, which looks identical to yours w/o the Tracker.autorun
Template.slider.helpers({
sliderVal: function() {
var slider = Slider.findOne(); // this guy is reactive, so when another client updates the Collection, it'll get pushed to us
if (slider) { Template.instance().$('#slider').data('uiSlider').value(slider.slide); // Template.instance() b/c `this` doesn't return a template instance in a helper
return slider.slide; // again, here you can return nothing if you'd rather have no text
}
}
});
-
1\$\begingroup\$ The finest first posts are definitely answers. Welcome to CodeReview, Carson. \$\endgroup\$Legato– Legato2015年04月22日 23:17:40 +00:00Commented Apr 22, 2015 at 23:17