Reputation: 151885
I have a custom block helper (essentially, an {{#each}} loop) that renders the results of a Mongo.Collection.find():
{{#sortable items=someCursor}}
{{> sortableItemTarget}}
{{/sortable}}
In the sortableItemTarget template event handlers, how do I access the parent data context, i.e. the collection (or at least cursor) that the item came from?
Because of a bug, custom block helper template event handlers don't have access to the parent data context.
In other words, if I run
var items = Mongo.Collection('items');
...
var item = items.findOne({...});
How can I easily remove item
from its collection with something like item._collection.remove()
?
The minimal code is in this GitHub repo.
Upvotes: 0
Views: 69
Reputation: 4138
I am not sure this answers your question as your github repo seems to add more complexity of how events access object data. But based on the code provided you can just use the transform option to make items.remove( item._id )
available wherever you have item
.
Like this:
var item = Items.findOne( {...}, {transform: function( i ){
i.remove = function() {return items.remove( i._id )};
return i;
}});
//then where ever you can access item
item.remove();
I tested this in a meteorpad based on the leaderboard example and it works well. Selecting a player removes it from the players collection.
Upvotes: 1
Reputation: 8154
I know I posted a comment already, but after thinking on this for 30sec I felt I should give this a more proper answer.
One of the tricks I have learned in my own voyage into Meteor is that, when dealing with helpers and event listeners, where the context of this
is pointed. For instance, if I have a {{#with XXX}}
block, then any event handlers or helpers that get called with will reference XXX
as their this
. Nice feature in that I can write my code in a VERY generic way to simply handle any one given element, and it gets multiplied and just "works" for a multitude by nature of Meteor.
Second, I do all my data manipulation through async Meteor.call
s. I haven't delved into doing a combined Client and Server Meteor.call yet, as I haven't had the need to, but I have looked at the code and it doesn't seem at all complicated in the least. I do this to preserve the reactivity, and to let Meteor do this "thang" and update the Templates as the data is updated.
Finally, when there is no easy way to get the data I want, I have found love in Blaze.getData(). It has proven indispensable in getting data at any part of my DOM.
So, to put this into practice, here is a sort example I pulled straight from my cranium, with no testing.
First, I need a loop in my Template. Something like:
<table>
{{#each myWidgets}}
<tr>
<td>{{myWidgetTitle}}</td>
<td>{{myWidgetData}}</td>
<td><button class="bntRemoveWidget">Remove Widget</button></td>
</tr>
{{/each}}
</table>
Here I assume my Template's data has a .myWidgets array, and each "widget" has a myWidgetTitle
and a myWidgetData
property. I also have a button to remove the widget.
Next, I need an event handler. Simple enough
Template.myWidgetTable.events({
'click .btnRemoveWidget': function(event, tmpl) {
var myWidget = Blaze.getData(event.getTarget()); // This bit of magic gets me the widget in context where the button was clicked!
Meteor.call('removeWidget', myWidget._id, function(err, result) {
if (err) {
// Do something with the error!
} else {
// Add some success message???
}
});
}
});
Finally, I need to write the method to handle the remove (I am not coding the guts as that's a separate discussion not related to the question):
Meteor.methods({
removeWidget: function(myWidgetId) {
// Select the item that contains the widget id, remove it, and save it back to the collection
}
});
Now, since my Template is reactive to the object that contains the myWidgets
array, simply updating the contents of the array on the server causes the appropriate chain reaction to make it so in the UI. Again, you can get "fancy" with the Meteor.call and Meteor.methods to make corresponding Client and Server versions, and what will happen is that the method runs on both, updating the Client so the UI gets the immediate update without waiting, but also updating the Server so the actual data in you DB is correct. Meteor is smart enough to reconcile the changes made to the Client against what was made in the Server for you when the publish channels finally sync up. It also supposedly can cache updates from the client and sync up when connections are restored, although I have not tested that yet at all.
Upvotes: 1