I want a paginated data table with edit and delete buttons on each row.
I tried using ephemer:reactive-datatables with Meteor event handlers for the buttons.
I put the object id in an html data attribute on the button.
The click event selector is for the class of the buttons.
The problem is that sometimes the event.target is the button and sometimes it is the icon in the button.
I was recommended to use $(this) i
nstead of $(event.target)
but the reactive-datatables package seems to be changing $(5his)
in the event handler to be a jquery datatables object.
How can I consistently and easily get the object id for the clicked button?
This seems like a relatively common thing to do so I am wondering if I have wandered off the “best practices” trail into the “i guess you could do that” wilderness.
Is there a better way to do this?
Thanks!
Shawn
adminPlans.html
<Template name="adminPlans">
<h1><tempAdmin Plans</h1>
<p>This is the plan admin page.</p>
<a href="/admin/plans?add=1" title="Add"><button type="button"><i class="fa fa-plus"></i> Add New Plan</button></a>
{{> ReactiveDatatable tableData=reactiveDataFunction options=optionsObject}}
</template>
adminPlans.js
plansTableData = function() {
return Plans.find().fetch();
};
var plansTableOptions = {
columns: [
{
title: “Actions”,
data: “_id”,
render: renderActions,
className: “actionsColumn”
},
{
title: “Name”,
data: “name”,
className: “nameColumn”
},
{
title: “Interval”,
data: “intervalType”,
render: renderInterval,
className: “intervalColumn”
},
{
title: “Trial Days”,
data: “trialDays”,
className: “trialColumn”
},
{
title: “Price”,
data: “price”,
render: renderPrice,
className: “priceColumn”
},
{
title: “Plan Id”,
data: “planId”,
className: “planIdColumn”
}
]
};
function renderActions(cellData, renderType, currentRow) {
var actionsHtml = '<a href="/admin/plans?edit=' + cellData + '" title="Edit"><button type="button"><i class="fa fa-edit"></i></button></a>';
actionsHtml += ' <a href="/admin/plans?remove=' + cellData + '" title="Remove"><button type="button" class="removePlanButton" data-id="' + cellData + '"><i class="fa fa-remove"></i></button></a>';
return actionsHtml;
}
function renderInterval(cellData, renderType, currentRow) {
return "" + currentRow.intervalCount + " " + cellData;
}
function renderPrice(cellData, renderType, currentRow) {
var priceHtml = "";
if (currentRow.currency === "USD") {
priceHtml = “$” + cellData;
} else {
priceHtml = cellData + " " + currentRow.currency;
}
return priceHtml;
}
Template.adminPlans.helpers({
reactiveDataFunction: function() {
return plansTableData;
},
optionsObject: plansTableOptions
});
Template.adminPlans.events({
'click .removePlanButton': function(event) {
event.preventDefault();
var jthis = $(this);
console.log("jthis: " + JSON.stringify(jthis));
console.log("class: " + jthis.attr(“class”));
var jtarget = $(event.target);
console.log("jtarget: " + JSON.stringify(jtarget));
console.log("class: " + jtarget.attr(“class”));
var jparent = jtarget.parent();
console.log("jparent: " + JSON.stringify(jparent));
console.log("class: " + jparent.attr(“class”));
console.log("data: " + jparent.data(“id”));
var id = jparent.data(“id”);
// XXX confirm dialog
console.log("Calling removePlan for id: " + id);
Meteor.call(“removePlan”, id);
}
});
Browser console output 1
this: {“0”:{“options”:{“columns”:[{“title”:“Actions”,“data”:"_id",“className”:“actionsColumn”,“sTitle”:“Actions”,“mData”:"_id",“sClass”:“actionsColumn”},{“title”:“Name”,“data”:“name”,“className”:“nameColumn”,“sTitle”:“Name”,“mData”:“name”,“sClass”:“nameColumn”},{“title”:“Interval”,“data”:“intervalType”,“className”:“intervalColumn”,“sTitle”:“Interval”,“mData”:“intervalType”,“sClass”:“intervalColumn”},{“title”:“Trial Days”,“data”:“trialDays”,“className”:“trialColumn”,“sTitle”:“Trial Days”,“mData”:“trialDays”,“sClass”:“trialColumn”},{“title”:“Price”,“data”:“price”,“className”:“priceColumn”,“sTitle”:“Price”,“mData”:“price”,“sClass”:“priceColumn”},{“title”:“Plan Id”,“data”:“planId”,“className”:“planIdColumn”,“sTitle”:“Plan Id”,“mData”:“planId”,“sClass”:“planIdColumn”}],“stateSave”:true,“stateDuration”:-1,“pageLength”:5,“lengthMenu”:[3,5,10,50,100],“columnDefs”:[{“targets”:"_all",“defaultContent”:"–––",“sDefaultContent”:"–––"}],“aoColumns”:[{“title”:“Actions”,“data”:"_id",“className”:“actionsColumn”,“sTitle”:“Actions”,“mData”:"_id",“sClass”:“actionsColumn”},{“title”:“Name”,“data”:“name”,“className”:“nameColumn”,“sTitle”:“Name”,“mData”:“name”,“sClass”:“nameColumn”},{“title”:“Interval”,“data”:“intervalType”,“className”:“intervalColumn”,“sTitle”:“Interval”,“mData”:“intervalType”,“sClass”:“intervalColumn”},{“title”:“Trial Days”,“data”:“trialDays”,“className”:“trialColumn”,“sTitle”:“Trial Days”,“mData”:“trialDays”,“sClass”:“trialColumn”},{“title”:“Price”,“data”:“price”,“className”:“priceColumn”,“sTitle”:“Price”,“mData”:“price”,“sClass”:“priceColumn”},{“title”:“Plan Id”,“data”:“planId”,“className”:“planIdColumn”,“sTitle”:“Plan Id”,“mData”:“planId”,“sClass”:“planIdColumn”}],“bStateSave”:true,“iStateDuration”:-1,“aLengthMenu”:[3,5,10,50,100],“aoColumnDefs”:[{“targets”:"_all",“defaultContent”:"–––",“sDefaultContent”:"–––"}],“iDisplayLength”:5}},“length”:1}
adminPlans.js:76 class: undefined
adminPlans.js:78 jtarget: {“0”:{},“context”:{},“length”:1}
adminPlans.js:79 class: removePlanButton
adminPlans.js:81 jparent: {“0”:{“sizzle1451884531682”:{“parentNode”:[277,33,true]}},“length”:1,“prevObject”:{“0”:{},“context”:{},“length”:1},“context”:{}}
adminPlans.js:82 class: undefined
adminPlans.js:83 data: undefined
adminPlans.js:86 Calling removePlan for id: undefined
Browser console output 2
adminPlans.js:75 jthis: {“0”:{“options”:{“columns”:[{“title”:“Actions”,“data”:"_id",“className”:“actionsColumn”,“sTitle”:“Actions”,“mData”:"_id",“sClass”:“actionsColumn”},{“title”:“Name”,“data”:“name”,“className”:“nameColumn”,“sTitle”:“Name”,“mData”:“name”,“sClass”:“nameColumn”},{“title”:“Interval”,“data”:“intervalType”,“className”:“intervalColumn”,“sTitle”:“Interval”,“mData”:“intervalType”,“sClass”:“intervalColumn”},{“title”:“Trial Days”,“data”:“trialDays”,“className”:“trialColumn”,“sTitle”:“Trial Days”,“mData”:“trialDays”,“sClass”:“trialColumn”},{“title”:“Price”,“data”:“price”,“className”:“priceColumn”,“sTitle”:“Price”,“mData”:“price”,“sClass”:“priceColumn”},{“title”:“Plan Id”,“data”:“planId”,“className”:“planIdColumn”,“sTitle”:“Plan Id”,“mData”:“planId”,“sClass”:“planIdColumn”}],“stateSave”:true,“stateDuration”:-1,“pageLength”:5,“lengthMenu”:[3,5,10,50,100],“columnDefs”:[{“targets”:"_all",“defaultContent”:"–––",“sDefaultContent”:"–––"}],“aoColumns”:[{“title”:“Actions”,“data”:"_id",“className”:“actionsColumn”,“sTitle”:“Actions”,“mData”:"_id",“sClass”:“actionsColumn”},{“title”:“Name”,“data”:“name”,“className”:“nameColumn”,“sTitle”:“Name”,“mData”:“name”,“sClass”:“nameColumn”},{“title”:“Interval”,“data”:“intervalType”,“className”:“intervalColumn”,“sTitle”:“Interval”,“mData”:“intervalType”,“sClass”:“intervalColumn”},{“title”:“Trial Days”,“data”:“trialDays”,“className”:“trialColumn”,“sTitle”:“Trial Days”,“mData”:“trialDays”,“sClass”:“trialColumn”},{“title”:“Price”,“data”:“price”,“className”:“priceColumn”,“sTitle”:“Price”,“mData”:“price”,“sClass”:“priceColumn”},{“title”:“Plan Id”,“data”:“planId”,“className”:“planIdColumn”,“sTitle”:“Plan Id”,“mData”:“planId”,“sClass”:“planIdColumn”}],“bStateSave”:true,“iStateDuration”:-1,“aLengthMenu”:[3,5,10,50,100],“aoColumnDefs”:[{“targets”:"_all",“defaultContent”:"–––",“sDefaultContent”:"–––"}],“iDisplayLength”:5}},“length”:1}
adminPlans.js:76 class: undefined
adminPlans.js:78 jtarget: {“0”:{},“context”:{},“length”:1}
adminPlans.js:79 class: fa fa-remove
adminPlans.js:81 jparent: {“0”:{},“length”:1,“prevObject”:{“0”:{},“context”:{},“length”:1},“context”:{}}
adminPlans.js:82 class: removePlanButton
adminPlans.js:83 data: 5681ee37fac82b23ef678f84
adminPlans.js:86 Calling removePlan for id: 5681ee37fac82b23ef678f84