Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Meteor update flot chart

When using Meteor 0.8.0, how do you update a flot chart when new data arrives? I looked at the example at Meteor-flot, but it is updating with fake data via a timer on the page. and not reactive data coming from a collection.

So far I have something like:

// returns an object with a label and an array of timestamp, value
// like { label:'test', data:[[1397605016000, 1332],[1397605616000,1356],[1397606216000,1380]]}
Template.example.helpers({
  readings: function(){
    DataReadings.find();
  }
});

Template.example.rendered = function() {
  $.plot ($("#flot"), [this.data.data], {
    series: {
      lines: {
        show: true
      },
      points: {
        show: true
      }
    },
    xaxis: {
      mode: 'time',
      timeformat: '%H:%M'
    }
  });
};

This works great for the initial render, but not sure how to go about updating the chart once new data arrives, which is about once every five minutes. So how to call the plot.setData(newData) & plot.draw() when new data arrives?

like image 390
Deke Avatar asked Nov 17 '25 20:11

Deke


1 Answers

One way to do it is using a cursor/collection observer. I'm using this method in my Meteor app to update a Flot chart and it works great.

After your initial plot creation in Template.example.rendered function, add a cursor observer that updates your chart anytime a new document is added (or removed) on the collection:

//  Subscribe to collection (or no need to do this if it's already done on your route)
Meteor.subscribe('dataReadings', someFilterVarOrNot);

//  Add a cursor observer for all documents added with a date greater 
//  than right now (uses moment.js)
//  (If you don't do this, you'll get an "added" fire for every document 
//  that's ALREADY been added - not sure why it does this but it does
dataReadingsObserveHandle = DataReadings.find({
  createdAt: {$gte: moment().toDate()}}).observe({

    //  Fires anytime a new document is added
    added: function(dataReading) {
      $('#flot').data("plot").setData(dataReading.data);
      $('#flot').data("plot").draw();

      //  Or setup whatever query/calculation you need to assemble a 
      //  new data set for your chart, there are also some other observers like
      //  observeChanges() which let you see how a document has changed versus
      //  being added or removed
    },

    //  Fires anytime a document is removed
    removed: function(removedDataReading) {
      //  Update and redraw chart like above...
  }
});

The dataReadingsObserveHandle is intentionally global so you can destroy it later because apparently a collection observer is server intensive. This doesn't necessarily have to be global if you have scope access to it wherever it would need to be destroyed:

//  Once your chart no longer needs to be updated call...
dataReadingsObserveHandle.stop();
dataReadingsObserveHandle = null;

I believe when a user navigates to a different template and is no longer looking at your chart, the observer automatically gets destroyed. See http://docs.meteor.com/#observe for more information.

I would love to hear about other methods to do this using ReactiveVar or Deps.dependency. Especially if they're more efficient

like image 176
evolross Avatar answered Nov 20 '25 11:11

evolross



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!