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:
Related
I use jQuery datatables checkboxes extension to give my table multi select function. When any row's checkbox is clicked, I retrieve all the selected rows' first cell's data send to server.
The code works in Chrome browser, but does not work in IE browser.
$(document).ready(function () {
var table = $('#tbl_inv').DataTable({
"paging": false,
//"ordering": false,
"info": false,
"searching": false,
'columnDefs': [
{
'targets': 0,
'checkboxes': {
'selectRow': true
}
}
],
'select': {
'style': 'multi'
},
'order': [[1, 'asc']]
});
$('#tbl_inv input[type="checkbox"]').on('change', function () {
$.ajax({
url: '/Invoices/Pickup?handler=CalcTotaltoPay',
data: {
invIds: $('#tbl_inv').DataTable().column(0).checkboxes.selected().join(),
clientId:1234
}
})
.done(function (result) {
freshResult(result);
});
// Iterate over all selected checkboxes
//$.each(table.column(0).checkboxes.selected(), function (index, rowId) {
// console.log(index + '---' + rowId)
// console.log(table.cell(index, 5).data())
//});
});
});
When I use IE browser, .column(0).checkboxes.selected() returns a list, this list not include current clicked checkbox state change. meaning, when checkbox checked, .column(0).checkboxes.selected() return a list not include current checkbox's data. when checkbox unchecked, .column(0).checkboxes.selected() return a list still include this checkbox's data.
This is due to the racing condition with jQuery DataTables Checkboxes plug-in. It handles change event internally to update the list of selected checkboxes. When you handle change event yourself, apparently in IE plug-in is still unaware of the change.
Try using columns.checkboxes.selectCallback option for handling event when state of the checkbox changes.
'columnDefs': [
{
'targets': 0,
'checkboxes': {
'selectRow': true,
'selectCallback': function(nodes, selected){
// Handle checkbox state change event
}
}
}
],
I am using a Kendo UI grid and for deleting a row I am using a custom button with bootstrap that when I click on it, with ajax I call a web api method to remove that row and if it is successfully deleted that row removes it from the DOM. (I'm not using the command destroy of kendo)
The problem I have is that if I try to filter that row that was removed, it appears again in the grid and it seems that it was not removed at all.
This is my Kendo UI grid:
var table = $("#grid").kendoGrid({
dataSource: {
transport: {
read: {
url: "/api/customers",
dataType: "json"
}
},
pageSize: 10
},
height: 550,
filterable: true,
sortable: true,
pageable: {
refresh: true,
pageSizes: true,
buttonCount: 5
},
columns: [{
template: "<a href='' class='btn-link glyphicon glyphicon-remove js-delete' title='Delete' data-customer-id= #: Id #></a>",
field: "Id",
title: " ",
filterable: false,
sortable: false,
width: 50,
attributes: {
style: "text-align: center"
}
}, {
field: "Name",
title: "Name",
width: 100,
}, {
field: "LastName",
title: "LastName",
width: 100,
}, {
field: "Email",
title: "Email",
width: 150
}]
});
And this is my jQuery code for deleting a row:
$("#grid").on("click", ".js-delete", function () {
var button = $(this);
if (confirm("Are you sure you want to delete this customer?")) {
$.ajax({
url: "/api/customers/" + button.attr("data-customer-id"),
method: "DELETE",
success: function () {
button.parents("tr").remove(); //This part is removing the row but when i filtered it still there.
}
});
}
});
I know that in jQuery DataTables when can do something like this:
table.row(button.parents("tr")).remove().draw();
How can i do something like this with Kendo UI using jQuery?
Don't ever play with a Kendo's widget DOM. Always use it's methods instead.
Using Grid's removeRow():
$("#grid").on("click", "button.remove", function() {
var $tr = $(this).closest("tr"),
grid = $("#grid").data("kendoGrid");
grid.removeRow($tr);
});
Demo
Using DataSource's remove():
$("#grid").on("click", "button.remove", function() {
var $tr = $(this).closest("tr"),
grid = $("#grid").data("kendoGrid"),
dataItem = grid.dataItem($tr);
grid.dataSource.remove(dataItem);
});
Demo
My usage was a little different. I have a custom delete button, so I needed to delete by ID, not UID.
You should be able to match on any field value instead of ID.
var grid = $("#grid").data("kendoGrid");
var dataItem = grid.dataSource.get(ID);
var row = grid.tbody.find("tr[data-uid='" + dataItem.uid + "']");
grid.removeRow(row);
We were trying to prevent messing with the controller, and this calls the existing delete function.
The removed row will be present in the kendo ui till you push changes to server.
To remove the row entirely you need to use
grid.saveChanges()
So the code below will remove row from server as well from ui
const row = $(e.target).closest('tr')[0];
const grid = $(e.target).closest('#grid').data("kendoGrid");
grid.removeRow(row);
grid.saveChanges() //comment out if you need to remove only from ui
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("");
}
I have a function that creates an instance of DataTables and for some reason it initializes n-times after destruction. I only noticed this because I add custom fields on init and they were multiplying. I could prevent that but that only deals with the symptom.
To clarify, after I "destroy: the instance and reinitialize it, to change the data source, if it's the second time it initializes twice. Three times if it's the 3rd time, etc.
I speculate that the table variable is part of the closure formed by the function because even if I set table = null the same thing happens.
How can I prevent this?
DataTables Function
/*Create a DataTable on tableElementID using pageUrl as the source*/
function ajaxLoadTable ( pageUrl, tableElementID ) {
window.table = $(tableElementID)
.on( 'init.dt', function () {
//The success function is used internally so it should NOT be overwritten, have to listen for this event instead
//Add our custom fields _length refers to an element generated datatables
if ( additionalElements.saveButton ) {
$(tableElementID + '_length').after('<div class="dataTables_filter"><button>Save All Edits</button></div>');
}
if ( additionalElements.selectState ) {
$(tableElementID + '_length').after('<div class="dataTables_filter"><label>Project State: <select name="projectState" style="width:auto;"><option>Select ...</option><option value="Active">Active</option><option value="Historical">Historical</option></select></label></div>');
}
if ( additionalElements.searchBox ) {
$(tableElementID + '_length').after('<div class="dataTables_filter"><label>Search:<input type="search" id="customSearch" style="width:auto;"></label></div>');
}
})
.DataTable({
"processing": true,
"serverSide": true,
"ajax":{
type: "POST",
url: pageUrl,
data: function ( additionalData ) {
$('.serverData').each( function( index, element ){
if( element.nodeName === "SELECT"){
additionalData[element.name.toUpperCase()] = element.options[element.selectedIndex].value;
return true; //return true is equivalent to continue for $.each
}
additionalData[element.name.toUpperCase()] = element.value;
});
},
dataType: "json"
},
"pageLength": 4,
"lengthMenu": [ 4, 8, 12, 16, 24 ],
"searchDelay": 1500,
"columnDefs":
{ "targets": 0,
"orderable": false,
"data": {
"_": "display"
}
}
});
}
Destruction Function
/*Load the selected project state*/
$('html').on( 'change' , '[name=projectState]' ,function(){
var currentState = $('option:selected', this).val();
$('#projectState').val(currentState);
//Remove the old table records and the datatables. Order matters, otherwise there is unsual behavior.
if( $.fn.DataTable.isDataTable( '#searchTable' ) ) {
window.table.destroy();
window.table = null;
}
$('.projectStateText').html( currentState );
//Get the new table records
ajaxLoadTable( *some undisclosed URL*, '#searchTable');
});
I have one button but I need two buttons and perform some MySql when they are clicked to get data from the underlying database.
How can I perform an event using these two buttons?
$(document).ready(function () {
var table= $('#example').dataTable( {
"ajax": "..//wp-content/plugins/jobify/Admin/data.txt",
"columnDefs": [ {
"targets": -1,
"data": null,
"defaultContent": "<button>View Posted Jobs</button>"
} ]
} );
$('#example tbody').on( 'click', 'button', function () {
//var data = table.row( $(this).parents('tr') ).data();
} );
} );
Just assign a class to each button and attach an event handler to each class.
$(document).ready(function () {
var table = $('#example').dataTable( {
"ajax": "../wp-content/plugins/jobify/Admin/data.txt",
"columnDefs": [ {
"targets": -1,
"data": null,
"defaultContent":
'<button class="btn-view" type="button">View Posted Jobs</button>'
+ '<button class="btn-delete" type="button">Delete</button>'
} ]
} );
// Handle click on "View" button
$('#example tbody').on('click', '.btn-view', function (e) {
//var data = table.row( $(this).parents('tr') ).data();
} );
// Handle click on "Delete" button
$('#example tbody').on('click', '.btn-delete', function (e) {
//var data = table.row( $(this).parents('tr') ).data();
} );
});