Below is my template helper code. The neat thing is that because I have it inside Deps.autorun, as soon as a new tag is added by one client, it is reactively available on all other clients as a new select2 option. I am using the 'tag' setting of select2 below, where you just pass an array of strings to the 'tag' option. You could also use the 'data' mode, in which case you have to pass an array of objects to the 'data' option, with each object having an 'id' property and a 'text' property.
Template.observationPostForm.rendered = function () {
var self = this;
self.myDeps = Deps.autorun(function () {
var cursor = Tags.findOne({'projectId': Session.get("currentProject")})
if (cursor && cursor.tags) {
var options = {
'multiple': true,
'selectOnBlur': true,
'tags': cursor.tags,
'tokenSeparators': [","],
'width': 'element'
};
self.$('#post-tags').select2(options);
}
});
};
On the server, I'm publishing a pseudo collection of tags. This pattern was inspired by the 'counts-by-room' example in the official Meteor Documentation.
Meteor.publish("tags", function (arguments) {
var self = this;
if (this.userId) {
var roles = Meteor.users.findOne({_id : this.userId}).roles;
if ( _.contains(roles, arguments.projectId) ) {
var observations, tags, initializing, projectId;
initializing = true;
projectId = arguments.projectId;
observations = Observations.find({'projectId' : projectId}, {fields: {tags: 1}}).fetch();
tags = _.pluck(observations, 'tags');
tags = _.flatten(tags);
tags = _.uniq(tags);
var handle = Observations.find({'projectId': projectId}, {fields : {'tags' : 1}}).observeChanges({
added: function (id, fields) {
if (!initializing) {
tags = _.union(tags, fields.tags);
self.changed("tags", projectId, {'projectId': projectId, 'tags': tags});
}
},
removed: function (id) {
self.changed("tags", projectId, {'projectId': projectId, 'tags': tags});
}
});
initializing = false;
self.added("tags", projectId, {'projectId': projectId, 'tags': tags});
self.ready();
self.onStop(function () {
handle.stop();
});
} //if _.contains
} // if userId
return this.ready();
});