Event only fires once when making Ajax request in jQuery - javascript

I have a couple of drop downs that are populated from SharePoint using SPServices. This part works great. But then, I have a button that on click loads data from SharePoint and uses the dropdown texts as filter to fetch the data that will populate a table using the DataTables plugin. This part works only once; if I click the button again, nothing happens.
This is how I populate the dropdowns:
$(document).ready(function () {
var theYear; // Selected Year
var theRO; // Selected RO
//Fills the Dropdown lists (Year and RO)
$().SPServices({
operation: "GetListItems",
async: false,
listName: "{ListID}",
CAMLViewFields: "<ViewFields><FieldRef Name='Fiscal_x0020_Year' /><FieldRef Name='Regional_x0020_Office' /></ViewFields>",
completefunc: function (xData, Status) {
//Add Select Value option
$("#dropdown").prepend($('<option>', {
value: '',
text: 'Select Fiscal Year'
}));
$("#dropdownRO").prepend($('<option>', {
value: '',
text: 'Select Regional Office'
}));
//Fetching Data from SharePoint
$(xData.responseXML).SPFilterNode("z:row").each(function () {
var dropDown = "<option value='" + $(this).attr("ows_Fiscal_x0020_Year") + "'>" + $(this).attr("ows_Fiscal_x0020_Year") + "</option>";
var dropDownRO = "<option value='" + $(this).attr("ows_Regional_x0020_Office") + "'>" + $(this).attr("ows_Regional_x0020_Office") + "</option>";
$("#dropdown").append(dropDown);
$("#dropdownRO").append(dropDownRO);
/////////////Deletes duplicates from dropdown list////////////////
var usedNames = {};
$("#dropdown > option, #dropdownRO > option").each(function () {
if (usedNames[this.text]) {
$(this).remove();
} else {
usedNames[this.text] = this.value;
}
});
////Deletes repeated rows from table
var seen = {};
$('#myTable tr, #tasksUL li, .dropdown-menu li').each(function () {
var txt = $(this).text();
if (seen[txt]) $(this).remove();
else seen[txt] = true;
});
});
} //end of completeFunc
}); //end of SPServices
$('.myButton').on('click', function () {
run()
});
}); //End jQuery Function
This is the function I need to run every time I click on "myButton" after changing my selection in the dropdowns:
function run() {
theYear = $('#dropdown option:selected').text(); // Selected Year
theRO = $('#dropdownRO option:selected').text(); // Selected RO
var call = $.ajax({
url: "https://blah-blah-blah/_api/web/lists/getByTitle('Consolidated%20LC%20Report')/items()?$filter=Fiscal_x0020_Year%20eq%20'" + theYear + "' and Regional_x0020_Office eq '" + theRO + "'&$orderby=Id&$select=Id,Title,Fiscal_x0020_Year,Notices_x0020_Received,Declined_x0020_Participation,Selected_x0020_Field_x0020_Revie,Selected_x0020_File_x0020_Review,Pending,Pending_x0020_Previous_x0020_Yea,Controversial,GFP_x0020_Reviews,NAD_x0020_Appeals,Mediation_x0020_Cases,Monthly_x0020_Cost_x0020_Savings,Monthly_x0020_Expenditure,Regional_x0020_Office,Month_Number", //Works, filters added
type: "GET",
cache: false,
dataType: "json",
headers: {
Accept: "application/json;odata=verbose",
}
}); //End of ajax function///
call.done(function (data, textStatus, jqXHR) {
var oTable = $('#example').dataTable({
"aLengthMenu": [
[25, 50, 100, 200, -1],
[25, 50, 100, 200, "All"]
],
"iDisplayLength": -1, //Number of rows by default. -1 means All Records
"sPaginationType": "full_numbers",
"aaData": data.d.results,
"bJQueryUI": false,
"bProcessing": true,
"aoColumns": [{
"mData": "Id",
"bVisible": false
}, //Invisible column
{
"mData": "Title"
}, {
"mData": "Notices_x0020_Received"
}, {
"mData": "Declined_x0020_Participation"
}, {
"mData": "Selected_x0020_Field_x0020_Revie"
}, {
"mData": "Selected_x0020_File_x0020_Review"
}, {
"mData": "Pending"
}, {
"mData": "Pending_x0020_Previous_x0020_Yea"
}, {
"mData": "Controversial"
}, {
"mData": "GFP_x0020_Reviews"
}, {
"mData": "NAD_x0020_Appeals"
}, {
"mData": "Mediation_x0020_Cases"
}, {
"mData": "Monthly_x0020_Cost_x0020_Savings",
"fnRender": function (obj, val) {
return accounting.formatMoney(val);
}
}, {
"mData": "Monthly_x0020_Expenditure",
"fnRender": function (obj, val) {
return accounting.formatMoney(val);
}
}],
"bDeferRender": true,
"bRetrieve": true,
"bInfo": true,
"bAutoWidth": true,
"bDestroy": true,
"sDom": 'T&;"clear"&;frtip',
"oTableTools": {
"aButtons": ["xls"],
"sSwfPath": "../../Style Library/js/datatables/TableTools/media/swf/copy_csv_xls_pdf.swf",
},
"sSearch": "Filter",
"fnDrawCallback": function () {
//Add totals row
var Columns = $("#example > tbody").find("> tr:first > td").length;
$('#example tr:last').after('<tr><td class="total"></td><td class="total"></td><td class="total"></td><td class="total"></td><td class="total"></td><td class="total"></td><td class="total"></td><td class="total"></td><td class="total"></td><td class="total"></td><td class="total"></td><td class="total"></td><td class="total"></td><td class="total"></td></tr>');
//Formating the Total row number to no decimals
$("#example tr:last td:not(:first,:last)").text(function (i) {
var t = 0;
$(this).parent().prevAll().find("td:nth-child(" + (i + 2) + ")").each(function () {
t += parseFloat($(this).text().replace(/[\$,]/g, '') * 1);
});
return parseInt(t * 100, 10) / 100;
});
//Format the monthly expenditure and savings to currency formatFormating the currency
var cell = new Array();
cell[0] = $('#example tr:last td:nth-child(12)').text();
cell[1] = $('#example tr:last td:nth-child(13)').text();
$('#example tr:last').find('td:nth-child(12)').html(accounting.formatMoney(cell[0]));
$('#example tr:last').find('td:nth-child(13)').html(accounting.formatMoney(cell[1]));
$('#example tr:last').find('td:last').hide();
} //hides extra td that was showing
}); //End of Datatable()
}); //End of call.done function
$('#theTableDiv').slideDown();
} //end of run() function
I'm not a programmer, I'm just trying to learn. I would appreciate any help. Thanks in advance

I would guess that you are replacing the part of the page where the button lives. (you really need to format your code more neatly for SO... use JSFiddle.net and their TidyUp button).
If that is the case you need to use a delegated event handler:
$(document).on('click', '.myButton', function () {
run()
});
This listens at a static ancestor of the desired node, then runs the selector when the event occurs, then it applies the function to any matching elements that caused the event.
document is the fallback parent if you don't have a convenient ancestor. Do not use 'body' for delegated events as it has odd behaviour.

Related

jQuery : How to bind an onClick Event to a DataTable row?

Currently, the dataTable is populated via the server side and everything is working. But I want to add Details|Edit|Delete actionLinks when a row is clicked.
Right now I have them showing in a column at the right side, but I want the links to appear when the user clicks on each row and I cannot workout how to implement it to show onClick.
Can someone please assist me in getting them to show on click? Thank you.
var dt = $('#datatableServer').DataTable({
"serverSide": true,
"ajax":
{
"type": "POST",
"url": "#Url.Action("DataHandler", "Department")"
},
"rowId": 'departmentID',
//"fnRowCallback": function (nRow, aData, iDisplayIndex) {
// nRow.setAttribute('id', aData[0]);
//},
"columns":
[
{
"data": "Name",
"searchable": true
},
{
"data": "Budget",
"searchable": false
},
{
"data": "StartDate",
"searchable": false
},
{
"data": "Administrator",
"searchable": true,
"orderable": false
},
{
// this is the Actions Column I want to show when a Datatable row is clicked, not under a "Action" column
mRender: function (data, type, row) {
var linkEdit = '#Html.ActionLink("Edit", "Edit", new {id= -1 })';
linkEdit = linkEdit.replace("-1", row.DT_RowId);
var linkDetails = '#Html.ActionLink("Details", "Details", new {id= -1 })';
linkDetails = linkDetails.replace("-1", row.DT_RowId);
var linkDelete = '#Html.ActionLink("Delete", "Delete", new {id= -1 })';
linkDelete = linkDelete.replace("-1", row.DT_RowId);
return linkDetails + " | " + linkEdit + " | " + linkDelete;
}
}
],
"order": [0, "asc"],
"lengthMenu": [[10, 25, 50, 100], [10, 25, 50, 100]]
});
$('#datatableServer tbody').on('click', 'tr', function () {
console.log('clicked');
// get the row Id
console.log(dt.row(this).data().DT_RowId);
});
}); // end of document.ready tag
I made my mRender function a separate function and then called it in the click event function for the datatable body.
function format (data, type, row) {
var linkEdit = '#Html.ActionLink("Edit", "Edit", new {id= -1 })';
linkEdit = linkEdit.replace("-1", row.DT_RowId);
var linkDelete = '#Html.ActionLink("Delete", "Delete", new {id= -1 })';
linkDelete = linkDelete.replace("-1", row.DT_RowId);
return linkEdit + " | " + linkDelete;
}
$('#dtServer tbody').on('click', 'td', function () {
var tr = $(this).closest('tr');
var row = dt.row(tr);
if (row.child.isShown()) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
}
else {
// Open this row
row.child(format(row.data())).show();
tr.addClass('shown');
}
});

Tabbing doesnt work for datatable

I m using jquery datatables in many pages and its working good in every page and in a single page its not working properly, i mean when i use tab to go through datatable, it works fine for the first time and when i try to do the same for second time, if i try to focus on any thing in few seconds in data table, the focus disappears and the foucs starts from the starting of the page.
Here goes the code
function tableCall(){
var clientId = $('#clientId').val();
var versionCount = $('#versionCount').val();
var fromDate = $('#fromDate').val();
var toDate = $('#toDate').val();
$.ajax({
url: auditTrail.props.reporttableURL,
type: "POST",
dataType: "json",
data: {
clientId:clientId,
versionCount:versionCount,
fromDate:fromDate,
toDate:toDate
},
success: function (data) {
searchJSON = data.data;
var len=searchJSON.length;
if (len > 0){
$('.no-data, #warning-sign').hide();
createTable();
}else{
$('.no-data').hide();
$('#warning-sign').show();
}
}
});
}
function createTable() {
wwhs.setADAAttrDynamic($('#auditTable'));
if ($.fn.DataTable.isDataTable('#auditTable')) {
// table.destroy();
$("#auditTable tbody").empty();
}
table = $('#auditTable').dataTable({
"searching":false,
"destroy":true,
"autoWidth": false,
"ordering": true,
"destroy":true,
"stateSave": true,
"drawCallback": attachEvents,
"stateLoadParams": function (settings, data) {
return false;
},
data: searchJSON,
columns: [{
data: "reportName"
}, {
data: "reportStatus"
}, {
data: "timeStamp"
}, {
data: "requestedBy"
}],
"columnDefs": [{
"render": function (data, type, row) {
if(row.reportStatus.toUpperCase() == 'PROCESSED')
return '<a class="blue-text" " data-name="'+ row.reportName +'">' + row.reportName + '</a>';
else
return row.reportName;
},
"width": "50%",
"targets": 0
}, {
"width": "15%",
"targets": 1
}, {
"width": "20%",
"targets": 2
}, {
"width": "15%",
"targets": 3
}]
});
}
I think the problem is because the datatable instance is not destroyed.
Since datatables saves all the nodes into an object and renders it when ever it wants, emptying the tbody doesnt do anything. it just removes the elements in the page which can be re-drawn/re-rendered by datatable from its stored object.
You can check if the object is already initialized and the destroy it before re-initializing.
if(typeof table != "undefined")
table.destroy();
So the final code will look something like
function tableCall(){
var clientId = $('#clientId').val();
var versionCount = $('#versionCount').val();
var fromDate = $('#fromDate').val();
var toDate = $('#toDate').val();
$.ajax({
url: auditTrail.props.reporttableURL,
type: "POST",
dataType: "json",
data: {
clientId:clientId,
versionCount:versionCount,
fromDate:fromDate,
toDate:toDate
},
success: function (data) {
searchJSON = data.data;
var len=searchJSON.length;
if (len > 0){
$('.no-data, #warning-sign').hide();
createTable();
} else {
$('.no-data').hide();
$('#warning-sign').show();
}
}
});
}
function createTable() {
wwhs.setADAAttrDynamic($('#auditTable'));
if ($.fn.DataTable.isDataTable('#auditTable')) {
if(typeof table != "undefined")
table.destroy();
}
table = $('#auditTable').dataTable({
"searching":false,
"destroy":true,
"autoWidth": false,
"ordering": true,
"destroy":true,
"stateSave": true,
"drawCallback": attachEvents,
"stateLoadParams": function (settings, data) {
return false;
},
data: searchJSON,
columns: [{
data: "reportName"
}, {
data: "reportStatus"
}, {
data: "timeStamp"
}, {
data: "requestedBy"
}],
"columnDefs": [{
"render": function (data, type, row) {
if(row.reportStatus.toUpperCase() == 'PROCESSED')
return '<a class="blue-text" " data-name="'+ row.reportName +'">' + row.reportName + '</a>';
else
return row.reportName;
},
"width": "50%",
"targets": 0
}, {
"width": "15%",
"targets": 1
}, {
"width": "20%",
"targets": 2
}, {
"width": "15%",
"targets": 3
}]
});
}

DataTables mRender function with view model

I'm implement table as http://www.datatables.net/examples/api/form.html, but in javascript I can't data-bind values from my viewmodel("vm") in "mRender". With test render function work correctly. How implement binding with viewmodel in javascript code?
function CreateNewDllTable(url, vm) {
var oTable = $('#test-table').dataTable({
"bProcessing": true,
"bServerSide": true,
"bPaginate": false,
"scrollY": "250px",
"bSort": false,
"bFilter": false,
"bInfo": false,
"sAjaxDataProp": "dataValues",
"sAjaxSource": url
},
"bAutoWidth": false,
"aoColumns": [
{ "mData": "name" },
{
type: 'text',
"mData": "description",
"mRender": function (data) {
if (data == true) {
return '<input type="text"/>';
} else {
return '<input type="text"/>';
}
}
},
{
"mRender": function (data) {
return "<select class='multiselect'>"
+ "<option>Value1</option>"
+ "<option>Value2</option>"
+ "<option>Value3</option>"
+ "<option>Value4</option>"
+ "<option>Value5</option>"
+ "</select>";
}
}
],
"fnDrawCallback": function () {
$("select.multiselect").multiselect();
},
}
For example binding in html:
<select class="multiselect" data-bind="
options: vm.types,
value: vm.selectedTypeId,
optionsText:'type',
optionsValue: 'typeId'">
</select>
For example you can used this code:
"mRender": function () {
var returnValue = "<select class='multiselect'>";
var types = vm.types;
var listItems = "";
for (var i = 0; i < types.length; i++) {
listItems += "<option value='" + types[i].typeId + "'" + " selected='selected'" + ">" + types[i].type + "</option>";
}
return returnValue.concat(listItems, "</select>");
}

How to add row number on table genareted by JQuery DataTable with server side datasource

I use JQuery DataTable to bind and show my data. However, I can't add row number to generated grid from client side. Here my code:
HTML
<table id="applications_list" class="table table-bordered datagrid">
<thead>
<tr>
<th><?php echo __('No.'); ?></th>
<th><?php echo __('Application Code'); ?></th>
<th><?php echo __('Application Name'); ?></th>
<th><?php echo __('Created By'); ?></th>
<th><?php echo __('Created Date'); ?></th>
<th><?php echo __('Action'); ?></th>
</tr>
</thead>
<tbody>
</tbody>
</table>
Javascript
$('#applications_list').dataTable({
"bLengthChange": false,
"bFilter": true,
"bFilter": false,
"bProcessing": true,
"bServerSide": true,
"sPaginationType": "full_numbers",
"sAjaxSource": config.siteURL + "/applications/ajax_index",
"sServerMethod": "POST",
"aoColumns": [
{ "mData": null, "bSortable": false },
{ "mData": "app_applicationcode", "sName": "app_applicationcode" },
{ "mData": "app_applicationname", "sName": "app_applicationname" },
{ "mData": "app_createdby", "sName": "app_createdby" },
{ "mData": "app_createddate", "sName": "app_createddate" },
{ "mData": "app_applicationcode", "bSortable": false, "mRender": function(data) {
return '<i class="">x</i>'
}},
],
"aaSorting": [[ 0, 'asc' ]],
});
I read documentation here, but it won't work. Can anyone help me to solve this problem?
Best solution:
"columns": [
{ "data": null,"sortable": false,
render: function (data, type, row, meta) {
return meta.row + meta.settings._iDisplayStart + 1;
}
},
......
]
For DataTables 1.10.4,
"fnCreatedRow": function (row, data, index) {
$('td', row).eq(0).html(index + 1);
}
Add following code in "fnRowCallback":
For Datatables 1.10
"fnRowCallback": function (nRow, aData, iDisplayIndex) {
var info = $(this).DataTable().page.info();
$("td:nth-child(1)", nRow).html(info.start + iDisplayIndex + 1);
return nRow;
}
The guide from official documentation didn't work on server side tables. The best answer I can get is from this answer (from another question), just to write a render function:
{
"data": "id",
render: function (data, type, row, meta) {
return meta.row + meta.settings._iDisplayStart + 1;
}
}
Go upvote that answer.
Since none of the solutions here worked for me, here is my solution for a server-side.
add the extra <th></th> in your table, this is to mark where the number is to be inserted.
add the following right after initiating the table, the same way you would add "ajax": {"url":"somepage"},
"fnCreatedRow": function (row, data, index) {
var info = table.page.info();
var value = index+1+info.start;
$('td', row).eq(0).html(value);
},
3.At the location where the variables are defined for the table columns, add this column { "data": null,"sortable": false },
so it looks like this:
"columns": [
{ "data": null,"sortable": false },
......]
4. To get rid of the sorting icon (up-down arrow), select the second column by adding , "order": [[ 1, 'asc' ]], the same way you would add "ajax"....
This is possible by make use of fnPagingInfo api in the rowCallback to get the page and the display length and use it to calculate the row number like this:
For DataTables < 1.10
$('#example').dataTable({
"fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
var page = this.fnPagingInfo().iPage;
var length = this.fnPagingInfo().iLength;
var index = = (page * length + (iDisplayIndex +1));
$('td:eq(0)', nRow).html(index);
}
});
For DataTables == 1.10
$('#example').dataTable({
"rowCallback": function( row, data, iDisplayIndex ) {
var info = this.api.page.info();
var page = info.page;
var length = info.length;
var index = = (page * length + (iDisplayIndex +1));
$('td:eq(0)', row).html(index);
}
});
NOTE: for DataTables < 1.10, you have to add the fnPageInfo.js script to your page
Official solution from DataTable:
table.on( 'order.dt search.dt', function () {
table.column(0, {search:'applied', order:'applied'}).nodes().each( function (cell, i) {
cell.innerHTML = i+1;
} );
} ).draw();
when we use Server Side Rendering, One of the Easy & Best Way for Display Auto Increment Sr No. instead of table row id... I used "Laravel Yajra DataTable"
simply use return meta.row + 1; .
see Below Example Code
columns: [
{data: 'SrNo',
render: function (data, type, row, meta) {
return meta.row + 1;
}
},
.... //your Code(Other Columns)
]
Or You can also Use like this
columns: [
{data: 'SrNo',
render: function (data, type, row, meta) {
return meta.row + meta.settings._iDisplayStart + 1;
}
},
.... //your Code(Other Columns)
]
Assuming the <?php echo __('No.'); ?> is the primary key from database you can use columnDefs to add the key as row number to each cell of a row like this
"columnDefs": [{
"targets": '_all',
"createdCell": function(cell, cellData, rowData, rowIndex, colIndex) {
$(cell).attr({'data-pk': rowData[0]});
}
}]
Where rowData[0] will be the primary key value.
Just add return meta.row + 1 this inside render function. For Example.
{
data: "",
render: function(rec, type, row, meta) {
return meta.row + 1;
}
}

jQuery Datatables.net - refresh table - getting null sAjaxSource

I have the following function which should update a datatable in my ASP.NET site master page:
function refreshTable(oTable) {
var table = $(oTable).dataTable();
var oSettings = table.fnSettings();
//Retrieve the new data with $.getJSON. You could use it ajax too
$.getJSON(oSettings.sAjaxSource, null, function (json) {
table.fnClearTable(this);
for (var i = 0; i < json.aaData.length; i++) {
table.oApi._fnAddData(oSettings, json.aaData[i]);
}
oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
table.fnDraw();
});
}
This function is then called to refresh a table if an attachment is added to the site - this is the datatable settings that it should refresh.
var DeleteClicked = false;
var oTable;
$(document).ready(function () {
oTable = $('#infoTable').dataTable({
"aaSorting": [[6, "desc"]],
"bProcessing": true,
"sAjaxSource": '/Web/Handlers/infoTableHandler.ashx',
"aoColumns": [
{ "mData": "ID", "bVisible": false },
{ "mData": "Type" },
{ "mData": "Received" },
{
"mData": "Action", "sWidth": "100px", "mRender": function (data, type, row) {
var id = row.ID;
return "<input type=button id=" + id + " onclick='DeleteFile(" + id + ")' class=buttonBlue value=Delete />";
},
},
{ "mData": "IsImage", "bVisible": false }
],
"bDeferRender": true,
});
However - if I open Developer Tools in Chrome I get an error message saying sAjaxSource is null so i cannot then get the value from it - so oSettings is null and then I cannot get access to the sAjaxSource - anyone see anything wrong here?
you're basically reinitializing your dataTable in the first row of refreshTable. Try instead:
function refreshTable() {
var oSettings = oTable.fnSettings();
...
}
and refer directly to the global oTable instead of your local table variable

Categories

Resources