I have a jquery datatable that populates from ajax but when I click on a row, the table click event handler does not fire. Here is my datatable:
function initDataTables(watchlist) {
$('#watchlistTable').DataTable({
ajax: {
url: "/MoneyMachine/getWatchlist.php",
type: "post",
data: {watchlist:watchlist}
},
columns: [
{ data: 'Symbol' },
{ data: 'CompanyName' },
{ data: 'ClosePrice', class: 'text-right' },
{ data: 'PricePctChangeToday', class: 'text-right'},
{ data: 'CAGR', class: 'text-right'},
{ data: 'BenchmarkCAGR', class: 'text-right'},
{ data: 'DivYield', class: 'text-right'},
{ data: 'ExDivDate'},
{ data: 'AppreciationPotential', class: 'text-right'}
],
responsive: true, //supposedly make table clickable but does nothing
destroy: true //A data table can only be initialized once. It must be destroyed so it can be initialized again.
});
}
I've tried a couple different click events like this:
$('.dataTable').on( 'click', '.dataTable', function () {
console.log("watchlistTable was clicked");
});
And like this:
$('#watchlistTable tbody').on( 'click', 'tr', function () {
console.log("watchlistTable was clicked");
});
And like this:
$('.display').on( 'click', '.display', function () {
console.log("watchlistTable was clicked");
});
But neither one fires. Here is the html for it:
<table id="watchlistTable" class="display" style="width:100%">
<thead>
<tr>
<th>Sym</th>
<th>Company Name</th>
<th>Price</th>
<th>Change%</th>
<th>CAGR</th>
<th>Benchmark<br>CAGR</th>
<th>Div<br>Yield%</th>
<th>Ex-Div<br>Date</th>
<th>App<br>Pot%</th>
</tr>
</thead>
</table>
My guess is you aren't including a <tbody> in the original html
Try adding it to the target selector and delegating to the table itself instead
$('#watchlistTable').on( 'click', 'tbody tr', function () {...
Note that $('.dataTable').on( 'click', '.dataTable', ... is trying to delegate to an existing class dataTable and would only be triggered on other elements with that class that are inside it. Since nothing in the html shown has that class it's not clear what that element would even be and I doubt you have nested elements with same class
Related
I have an issue, when I bind data with kendo to a Table I'm using a kendo.data.DataSource object and I'm binding to a table like:
<table class="myClass" id="myTable">
<thead>
<tr>
<th data-bind="visible:Name">Name.Title"</th>
<th data-bind="visible:Type">Type.Title"</th>
<th data-bind="visible: DateAdded">"CreatedDate.Title"</th>
</tr>
</thead>
<tbody id="contactsListView" data-role="listview"
data-bind="source: ListViewSource"
data-template="Template"></tbody>
</table>
on JS I am filling like this:
ListViewSource: new kendo.data.DataSource({
serverPaging: true, // <-- Do paging server-side.
serverSorting: true, // <-- Do sorting server-side.
transport: {
read: {
data: function () {
return globalVariableWithObjectList;
}
}
},
schema: {
data: function () {
return globalVariableWithObjectList;
}
}
}),
and it works for fill table on the first load, but if with some actions I add or delete an element It does not refresh on the table. I'm trying to refresh with:
ListViewSource.read();
It works when I have the kendo.data.DataSource like this:
contactsListViewSource: new kendo.data.DataSource({
serverPaging: true, // <-- Do paging server-side.
serverSorting: true, // <-- Do sorting server-side.
transport: {
read: {
url: myUrl,//Where I'm getting the data
dataType: "json",
type: "POST"
}
},
pageSize: 5,
sort: { field: "CreatedDate", dir: "desc" },
schema: {
data: function () {
return globalVariableWithObjectList;
}
}
}),
I am trying to reduce ajax numerous calls with only one when multiple data to update is needed, and storing data in global variables so that I can use them later. But the read() function for kendo.data.DataSource only refresh table data when it calls for an ajax request and non when I try to get data from the global variable, does anyone knows how can I make it work while reading from the variable ?
Use contactsListViewSource.add(newRecord); for adding new records to the data source, it will automatically bind to HTML list (MVVM) and display it.
Call contactsListViewSource.sync() to send data to server. contactsListViewSource.sync() will call transport.create method if new records are added.
Working example: ListView MVVM
I was unable to utilize the jQuery datatable plugin here:
https://editor.datatables.net/examples/inline-editing/simple
I kept getting an error, so I just dropped it and decided to do it myself.
Starting with the datatable:
$.ajax({
url: 'api/searchVoyageInfo.php',
type: 'POST',
data: '',
dataType: 'html',
success: function(data, textStatus, jqXHR){
var jsonObject = JSON.parse(data);
var table = $('#example1').DataTable({
"data": jsonObject,
"columns": [{
{ "data": "COLUMN1" },
{
"data": "COLUMN2",
"fnCreatedCell": function (nTd, sData, oData, iRow, iCol)
{
$(nTd).html("<a href='#' class='checkBound'>"+oData.COLUMN2+"</a>
<input type='text' class='editbound'
id='editbound' data-uid='"+oData.VOYID+"'
data-editbound='"+oData.COLUMN2+"' value='"+oData.BOUND+"
display: none;' />");
}
},
{ "data": "COLUMN3" },
// few more columns
}],
"iDisplayLength": 50,
"paging": true,
"bDestroy": true,
"autoWidth": true,
"dom": 'Bfrtip',
"buttons": [
// some extend buttons
]
});
},
error: function(// some stuff){
// do some other stuff
// this part is not important
}
});
Within COLUMN2, you should see a class 'checkBound' which is visible when the page loads. There is also an input class 'editbound' which is not visible.
Here is the function that is supposed to hide class 'checkBound' and then display class 'editbound':
$('#example1').on('click', 'tr > td > a.checkBound', function(e)
{
e.preventDefault();
var $dataTable = $('#example1').DataTable();
var tr = $(this).closest('tr');
var data = $dataTable.rows().data();
var rowData = data[tr.index()];
$('.checkBound').hide();
$('.editbound').show();
});
Using the above, when the page is finished loading, the datatable is displayed with no problem.
Upon clicking one of the cells with class 'checkBound' to display the input class 'editbound', the input does display itself, but it also displays every other cell in the column.
Before click:
After click:
As you can see, the first cell in the BOUND column is the cell that was clicked. But when clicked, the rest of the cells were activated. I want to prevent this from happening.
How can I make this work?
This is the way i created a column with a button in it . You should be able to do similar instead of button !
fields: [
{ name: "column_id", title:"View" ,itemTemplate: function(value) {
return $("<button>").text("buttontitle")
.on("click", function() {
//do something
return false;
});
}]
This is how I (somewhat) solved my problem. In the datatable section, I added an ID field called VOYID and included that ID with the class in the href and the input:
"data": "COLUMN2",
"fnCreatedCell": function (nTd, sData, oData, iRow, iCol)
{
$(nTd).html("<a href='#' class='checkBound"+oData.VOYID+"' id='checkBound'>"+oData.COLUMN2+"</a>
<input type='text' class='editbound"+oData.VOYID+"'
id='editbound' data-uid='"+oData.VOYID+"'
data-editbound='"+oData.COLUMN2+"' value='"+oData.BOUND+"
display: none;' />");
}
Then down in the button click section, I utilized the rowData to check for the exact class. This way, when you click the link, only the unique class will open and not all of the cells in the column:
$('#example1').on('click', 'tr > td > a.checkBound', function(e)
{
e.preventDefault();
var $dataTable = $('#example1').DataTable();
var tr = $(this).closest('tr');
var data = $dataTable.rows().data();
var rowData = data[tr.index()];
var voyid = rowData.VOYID;
$('.checkBound'+voyid).hide();
$('.editbound'+voyid).show();
});
Now, when I click on the link, it is only that cell that gets the input activated:
I have a kendo grid with a detail template, which I wish to clear if the user clicks on the clear command in the parent row.
I managed to get this to work, but as soon as I set the value on the dataItem, the row detail collapses, which causes the user to loose his place.
function clearDetails(e) {
var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
dataItem.set("City",""); // causes row detail collapse
}
$(document).ready(function () {
$("#grid").kendoGrid({
dataSource: {
type: "odata",
transport: {
read: "https://demos.telerik.com/kendo-ui/service/Northwind.svc/Customers"
},
},
columns: [{
field: "ContactName",
title: "Contact Name",
width: 240
}, {
field: "Country",
width: 150
}, { command: { text: "Clear", click: clearDetails }, title: " ", width: "180px" }],
detailTemplate: kendo.template($("#myRowDetailTemplate").html())
})
});
Working example:
https://jsbin.com/xuwakol/edit?html,js,output
Is there a way I can still clear the values in the row detail, without it collapsing.
I had the same issue I got around it by using the dataBinding function within the kendo grid.
Basically it checks for an item change event and will cancel the default action to close the grid. This allowed me to continue to use the set method.
Example:
$("#grid").kendoGrid({
dataBinding: function (e) {
if (e.action == "itemchange") {
e.preventDefault();
}
},
});
}
I managed to get this right by not using the set method on the dataItem. http://docs.telerik.com/kendo-ui/api/javascript/data/observableobject#methods-set
I just changed the value on the dataItem, dataItem.City =""; and with the help of jquery selectors cleared the value of the textarea.
function clearDetails(e) {
var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
dataItem.City ="";
$(e.currentTarget).closest(".k-master-row").next().find("textarea[name='City']").val("");
}
My use case is a datatable in which a user may select a row.
My table:
ts_table = $('#ts_table').DataTable({
iDisplayLength: 5,
lengthMenu: [5, 10, 20, 50, 100],
order: [[ 1, "asc" ]],
columns : [
{data:'ts_id'},
{data:'ts_name', width: '20%'},
{data:'ts_desc', width: '80%'}
],
columnDefs: [{
targets: [ 0 ],
visible: false,
searchable: false}
]
});
My event handler code is called by client generated events (document ready and when a data tables source is updated by the user):
function process_all_test_sets(msg) {
if (ts_table.data().any()) {
ts_table.rows().remove().draw();
} else {
all_test_sets_array = msg.data.split("|");
test_set_list = JSON.parse(all_test_sets_array[1]);
console.info("Adding rows to test set table.");
ts_table.rows.add(test_set_list).draw();
$('#ts_table tbody').on('click', 'tr', function (event) {
data = ts_table.row(this).data();
console.info("Clicked " + this);
if ($(this).hasClass('selected')) {
$(this).removeClass('selected');
test_set_test_sets = [];
}
else {
$(this).removeClass('selected');
$(this).addClass('selected');
if (test_set_test_sets.length > 0) {
test_set_test_sets.shift();
}
test_set_test_sets.push(data);
}
});
}
}
My problem is that the event handler doesn't add the selected class to my row every other time I try to refresh data (but not the document), even though I can see it populating and clearing test_set_test_sets as it should.
Help?
Thanks.
Most likely the problem is that you call process_all_test_sets() multiple times and therefore define event handler multiple times.
Instead you need to define your event handler only once and move it out of process_all_test_sets().
For example:
ts_table = $('#ts_table').DataTable({
// ...
});
$('#ts_table tbody').on('click', 'tr', function (event) {
// ...
});
function process_all_test_sets(msg) {
// ...
});
Alternatively you can use off() method to remove previously defined event handler. For example:
$('#ts_table tbody').off('click', 'tr');
$('#ts_table tbody').on('click', 'tr', function (event) {
// ...
});
I´m trying to bind and event inside a RowTemplate to a viewModel function, using Kendo Grid MVVM.
However, after calling kendo.bind an error is displayed in then console, and the event does not get fired, however the grid displays correctly. Here is the error:
Uncaught Error: The mouseover binding is not supported by the button element kendo.editor.js:890
I tried to change the element type inside the row template to any other thing, with same results.
Here is my html code:
<div id="content">
<div>
<div id="grid" data-role="grid" data-bind="source: ordersSource"
data-selectable="True" data-columns='["OrderID", "ShipName", "ShipCity"]' data-row-template="rowTemplate" />
</div>
</div>
<script id="rowTemplate" type="text/x-kendo-template">
<tr data-uid="#= uid #">
<td><button data-bind="mouseover: listener">#: OrderID #</button></td>
<td>#: ShipName #</td>
<td>#: ShipCity #</td>
</tr>
</script>
And here is my viewModel code:
var ordersDatasource = new kendo.data.DataSource({
type: "odata",
transport: {
read: "http://demos.kendoui.com/service/Northwind.svc/Orders"
},
schema: {
model: {
id: "OrderID",
fields: {
OrderID: { type: "number" },
ShipName: { type: "string" },
ShipCity: { type: "string" }
}
}
},
pageSize: 5,
});
var viewModel = kendo.observable({
ordersSource: ordersDatasource,
listener: function (e) {
alert("Event: " + e.type);
}
});
kendo.bind($('#content'), viewModel);
Here is the jsFiddle if you want to try.
The first column button should fire the event when passing the mouse over it, however it does not.
The correct syntax to bind events is:
<button data-bind="events: { mouseover: listener }">#: OrderID #</button
(updated demo)