1
\$\begingroup\$

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):

Live example

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>
\$\endgroup\$
2
\$\begingroup\$

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
    }
  }
});
\$\endgroup\$
  • 1
    \$\begingroup\$ The finest first posts are definitely answers. Welcome to CodeReview, Carson. \$\endgroup\$ – Legato Apr 22 '15 at 23:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.