I’m currently working on an integration of jsTree into Meteor as a Blaze template. The data source is a Mongo collection. jsTree loads the content node by node using a function. The code looked like this before:
Template.TreeView_content.onRendered(function() {
let dataContext = Template.currentData();
let collection = dataContext.collection;
// Function to retrieve child nodes
function getNodes(parent) {
return collection.find({parent}).map( (item) => {
item.id = item._id;
item.text = item.name;
Tracker.nonreactive(function() {
item.children = collection.find({parent: item._id}).count() > 0;
});
delete item.parent;
return item;
});
}
Tracker.autorun(function(computation) {
if (computation.firstRun) {
this.$('.js-treeview-content').jstree({
core: {
data: function(node, callback) {
// This function is called, when a node is opened
if (node.id === '#') {
callback(getNodes(null));
} else {
callback(getNodes(node.id));
}
}
}
});
} else {
console.log("refresh");
this.$('.js-treeview-content').jstree().refresh();
}
});
});
You see the getNodes()
function, which is called, when the tree is initialized (all folders are closed), and afterwards, when the user opens a folder, to load the child nodes.
This works quite well – until a change in the database happens. This change is not shown, except for the root node. Why? Only the first getNodes()
call is reactive, afterwards Tracker.active
is false.
To overcome this, I created a new function:
// function inspired from tracker.js
function useComputation(c, f) {
let savedComputation = Tracker.currentComputation;
Tracker.currentComputation = c;
Tracker.active = !! c;
f();
Tracker.currentComputation = savedComputation;
Tracker.active = !! savedComputation;
}
and call it from the data function:
[…]
data: function(node, callback) {
// The computation is reused to trigger only one refresh of the
// complete tree.
useComputation(computation, function() {
if (node.id === '#') {
callback(getNodes(null));
} else {
callback(getNodes(node.id));
}
});
}
[…]
Finally, this works well for me. Unfortunately, I didn’t find a solution, where I may not set Tracker.currentComputation
directly.
So, I suggest to implement this contrary of Tracker.nonreactive
directly as part of the Tracker. I’m able to provide a PR, but I wanted to ask the community first.