Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Meteor avoid double refreshes when third party widget changes it's own reactive datasource

I have a jsTree which I am trying to bi-directionally "connect" to a Meteor collection. Right now I automatically trigger a jsTree.refresh() whenever the collection updates with the help of .observeChanges:

FileTree.find().observeChanges({
  added: function() {
    $.jstree.reference('#fileTree').refresh();
  },
  changed: function() {
    $.jstree.reference('#fileTree').refresh();
  },
  removed: function() {
    $.jstree.reference('#fileTree').refresh();
  }
});

I want to allow editing of the database by dragging things around in jsTree. Here's how it would look:

  1. User drags element to new location.
  2. jsTree updates the location of the element in the tree.
  3. jsTree calls event handler
  4. Event handler updates database

My problem is, if I understand everything correctly, is that the database update would trigger the observeChanges event that I set up earlier. That would cause yet another refresh of the tree. That causes an annoying flicker which would interrupt users. (i.e. the file browser would be unusable for about 0.75s after every drag/drop operation.)

How can I prevent this unneeded update, or is there a better way to structure my interface with jsTree that would prevent this problem.

like image 759
BonsaiOak Avatar asked Sep 23 '14 18:09

BonsaiOak


1 Answers

Have you seen this?

  • https://github.com/tobkle/meteor-jstree-example
  • https://github.com/tobkle/meteor-jstree

It looks like he/she is using autorun vs. observeChanges but is mostly the same concept as yours:

Template.showtree.rendered  = function(){

  var self  = this;
  var nodes = [];

  Nodes1  = $('#tree1').tree();
  Nodes2  = $('#tree2').tree();

  if (!self.handle){
    self.handle = Meteor.autorun(function(){
      // refresh trees on new data
      nodes = Nodes.find();
      Nodes1.tree('option', 'data', 'Projects');
      Nodes2.tree('option', 'data', 'Contexts');
    }); //self.handle
  } // if (!self.handle)
}

If this is something only a single user would be editing (at a time) then perhaps you simply don't refresh it based on DB updates, and leave the tree as an interface to author, only.

If it needs to refresh based on DB updates (from other users, or just to be in sync), you might consider changing your workflow/logic:

  1. the changed.jstree event, updates the database locally, blocking
  2. the autorun triggers the refresh in jstree

which should, in theory, only result in 1 refresh vs. 2 or 3

Or if you really want to limit re-draws... you could find the old parent node and the new parent node and only us refresh_node(obj) to refresh just those changes nodes:

refresh_node (obj)

refreshes a node in the tree (reload its children) all opened nodes inside that node are reloaded with calls to load_node.

like image 106
zeroasterisk Avatar answered Nov 07 '22 21:11

zeroasterisk