When I construct a normal table and give each column a distinct class, the classes are responsive for all rows. However, when I call .dataTable() on my table, only page 1 of the paginated results is responsive. Page 2 and beyond are not responsive.
Example code:
var dataTableID = 'questionsTable';
var columns = {
questionID: "ID",
CategoryString: "Cat",
difficultyLevel: "Diff",
timesAsked: "Qty",
questionText: "Question Text"
};
// my own little function that builds the HTML table. <TD> classes are column names
//-- eg .questionID, .CategoryString, etc
var tableHTML = makeTable(questions, columns);
$('#' + dataTableID).html(tableHTML);
// dataTable works nicely except only page 1 .click is responsive!
$('#' + dataTableID).dataTable();
// works fine if I remove .dataTable() above. ONLY works for first page of results
// if I keep .dataTable()
$('.questionID').on("click", function() {
alert('Click called');
});
When using pagination, dataTables change the visible rows by moving <tr>'s back and forth the DOM. $('.questionID').on is processed for columns on the first page only, since those columns is the only visible (accessible) columns after initialization.
So you must assign the click handler (or whatever you want to attach) on page change rather than on initialization. Here by the use of the fnDrawCallback event :
function clickHandler() {
alert('Click called');
}
var dataTable = $('#example').dataTable({
fnDrawCallback : function() {
$('.questionID')
.off("click", clickHandler)
.on("click", clickHandler)
}
});
see demo -> http://jsfiddle.net/U9Jmg/
Notice the use of .off. dataTables actually moves the <tr>'s back and forth the DOM and a table in memory, including any attached events. If previous attached events is not released, we will end up in multiple alerts for each column.
Also note I have only used only one class .questionID for all the columns in the demo. The example is 1.10.x but this works in 1.9.x as well.
As you can see of the comments below, you could also use a delegated event instead of direct event binding. It changes the setup and perhaps it is not suitable for your needs, but anyway :
$('#example tbody').on('click', '.questionID', clickHandler);
see demo -> http://jsfiddle.net/L29Dq/
When using DataTables pagination feature (as you do), only the first page of your data is present in the dom when you attach the click event handler. That's why the handler is attached to the elements on the first page and only to those elements.
When going to another page, DataTables will redraw the table which in effect removes the attached event handler. You have to reattach the event handler after every table draw. The drawCallback option should be the right place for that:
$('#' + dataTableID).dataTable({
"drawCallback": function(settings){
$('.questionID').on("click", function(){
alert('Click called');
});
}
});
As #davidkonrad pointed out in his answer, the click handler should be removed (using off) to avoid handling the event multiple times.
The DataTables page has a section on this as well: Advanced Initialisation - DOM/jQuery events. The example there uses delegated events.
Related
I am trying to trigger an onClick event when click on next or previous buttons in data tables. I checked the IDs of the buttons and they are auto generated. couldn't use those IDs. Is this possible ?
You have a page.dt event, fired each time the paging is updated :
table.on('page.dt', function() {
var info = table.page.info();
console.log('Showing page: '+info.page+' of '+info.pages);
});
If you want to target click on the previous / next buttons you can easily do that. To my experience dataTables seems to "eat" the click event simply by updating the view immediately - but you can stay upfront in the chain by listening on the mousedown event instead :
$('.dataTables_wrapper').on('mousedown', '.previous', function() {
console.log('previous clicked')
})
$('.dataTables_wrapper').on('mousedown', '.next', function() {
console.log('next clicked')
})
You need to use a delegated event handler because the dataTable controls is recreated each time the dataTable is redrawn. .dataTables_wrapper, .next and .previous is common for all dataTables.
demo -> http://jsfiddle.net/6jpbyvd4/
I've got a nested grid within my grid, and it works perfectly, but the client doesn't like to use the arrow on the left and asked for a button to be added in order to show the child grid.
The example on the Kendo website shows how to automatically open the first row, I just want a way to expand the grid from a custom control in the same way that the left selector does it.
I've got the custom command working, and it executes the sample code, but I just need some help with the javascript required to make it work for the current row.
columns.Command(command =>
{
command.Edit().Text("Edit").UpdateText("Save");
command.Destroy().Text("Del");
command.Custom("Manage Brands").Click("showBrandsForAgency");
And the js with the standard example of opening the first row:
function showBrandsForAgency(e) {
this.expandRow(this.tbody.find("tr.k-master-row").first());
}
Please help by giving me the js required to expand the row clicked and not the first row?
* EDIT *
Modified the solution provided by Atanas Korchev in order to get it to work on only the button and not the whole row.
I'd prefer a solution that uses the function showBrandsForAgency instead of a custom funciton but this does the job:
$(document).ready(function () {
$("#grid").on("click", "a", function (e) {
var grid = $("#grid").data("kendoGrid");
var row = $(this).parent().parent();
if (row.find(".k-icon").hasClass("k-minus")) {
grid.collapseRow(row);
} else {
grid.expandRow(row);
}
});
});
You can try something like this:
$("#grid").on("click", "tr", function(e) {
var grid = $("#grid").data("kendoGrid");
if ($(this).find(".k-icon").hasClass("k-minus")) {
grid.collapseRow(this);
} else {
grid.expandRow(this);
}
});
When using jQuery on the function context (available via the this keyword) is the DOM element which fired the event. In this case this is the clicked table row.
Here is a live demo: http://jsbin.com/emufax/1/edit
Same results just Simpler, faster, and more efficient:
$("#grid").on("click", "tr", function () {
$(this).find("td.k-hierarchy-cell .k-icon").click();
});
I am using the colreorderwithresize.js plugin. Everything works fine, but most of the times the table is not getting aligned with header when the header is resized. I am trying to figure out if there is a call back function associated with resize such that I can call oTable.fnAdjustColumnSizing() whenever resize happens.
I tried adjusting column width using fndrawcallback but this creates performance issues when filtering the data (since this is invoked every time the data changes in the table).
"fnDrawCallback": function(oSettings) {
setTimeout( function () {
oTable.fnAdjustColumnSizing();
}, 3000 );},
Thanks,
Barani
Kike table (CSS class) was overriding datatable (class) hence I was not able to use any of the datatables function on these tables hence I came up with a solution as below,
function resizeDataTable(dataTableid){
$("#" + dataTableid).removeClass('kiketable-colsizable'); // Remove kike class
var oTable = $("#" + dataTableid).dataTable();
$(oTable).css({ width: $(oTable).parent().width() }); // Perform datatable functions
oTable.fnAdjustColumnSizing();
$("#" + dataTableid).addClass('kiketable-colsizable'); // Add kike class
}
This works flawlessly.
Pasting Allans' comments below for others who are in search of this feature......
Looking at the plug-in's code - it doesn't look like it, although I'm sure one could easily be added in the drag method.
I think you'll need to debounce (throttle) the call to fnAdjustColumngSizing one way or another though.
http://www.datatables.net/forums/discussion/13764/is-there-a-callback-function-for-colresize#Item_2
This jQuery selector matches a Rails 3 HTML form for a new model: $('form[id^="new_"]')
I'd like to have a simple focus function run each time a matching form loads. Sometimes the forms are loaded via a simple GET but also via Ajax. In the latter case, the content returned can be either HTML or escaped JS.
I was hoping jQuery would be able to match all cases via the selector, .on(), and the "load" event, but I can't seem to make that work for ANY case. Code:
$(document).ready(function() {
$('form[id^="new_"]').on("load", function(){
console.log("Matched!")
});
})
Any ideas?
Thanks Justice. I'm afraid I wasn't able to get your code to work. I'm using the following callback with the new custom event defined outside it as shown and I don't think the $('form') is triggering the event.
$('.shows-children').bind('ajax:success', function(evnt, data, status, xhr){
var boxSelector = '#' + $(this).data("shows");
$(boxSelector).html(xhr.responseText);
$('form').trigger('customevent');
});
$(document).on('customevent','form[id^="new_"]', function(){
console.log('Matched!')
});
(I'm surprised it seems more involved than expected to have jQuery act on HTML returned in an Ajax response.)
$(document).on("change","form[id^=\"new_\"]" function(){
console.log("Matched!")
});
For delegation, you want to delegate the original selector to a parent, as the event will bubble up.
However, load does NOT bubble up. In this case, change may suffice, but it'll trigger and attempt to see if the delegate is valid every time the document changes.
I would then suggest that you create a custom event after AJAX loads for the form.
Example:
$(document).on("customevent","form[id^="new_"]" function(){
console.log("Matched!")
$.ajax(url, function(response){
//success
$(document).append(response);
$('form').trigger('customevent');
});
});
HTH
I have a grid with store: cdStore defined. The grid's records are edited using a form which is bound to the grid data. When updating a record, I would like for the refreshed records to show in the grid.
Currently I have
handler : function() {
areaForm.getForm().submit({
params: { action: "update" }
});
cdStore.loadPage(cdStore.currentPage);
areaGrid.doLayout();
}
It seems like this fails sometimes and older data remains displayed in the grid - perhaps doLayout() is called before the page is fully loaded.
Can I trigger a doLayout on loadPage somehow?
// ...
cdStore.load({
callback: function(){areaGrid.doLayout();},
page: cdStore.currentPage
});
Update
I would appreciate a line or two with an explanation if you would be so kind
You said that "doLayout() is called before the page is fully loaded" and you were right. So the doLayout must be called after the data is loaded. The one way to do that is to use load method. You can pass array of options into this method:
store.load({
page: 2,
limit: 50,
// and
callback: function(){ /*do something*/ }
});
The function you pass as callback is called exactly after the data is loaded. So doLayout() put into callback produces correct behaviour.