Related
I am working on a table with data where one of the columns is a checkbox, and the user can check which rows they want to be exported to csv / excel files.
https://jsfiddle.net/martinradio/bLp2jz4e/12/
My jsfiddle example works correctly for non filtered data, if the table searchbox is empty and you click the 'select all' column, it will accurately select all and deselect all.
But if you search for something like 'x', and then click the 'select all' first column checkbox, it selects all results but doesnt reflect the change in the column checkbox?
My datatable is declared like so:
var myProductGapsTable = $('#myProductGapsTable').DataTable({
data: dataSet,
retrieve: true,
"language": { "emptyTable": "No table data availiable."},
"sDom": 'Bfrtip',
"paging": false,
buttons: [
{
extend: 'excelHtml5',
text: 'excel',
//exportOptions: { modifier: { page: 'current' } }
exportOptions: { rows: { selected: true, search: 'applied' } }
},
{
extend: 'csvHtml5',
text: 'csv',
exportOptions: { rows: { selected: true, search: 'applied' } }
},
],
/*
responsive: {
details: {
type: 'column',
target: -1,
}
},
*/
columnDefs: [ {
targets: -1,
orderable: false,
searchable: false,
className: 'control',
}, {
targets: 0,
orderable: false,
searchable: false,
className: 'selectall-checkbox',
} ],
select: {
style: 'multi',
selector: 'td:first-child',
search: 'applied'
},
order: [ 1, 'asc' ],
});
And I'm using the following 3 functions to handle the checkboxes and what happens when you click 'select all':
// On DataTables select / deselect event check / uncheck all checkboxes. And deal with the checkbox
// in the thead (check or uncheck).
myProductGapsTable.on('select.dt deselect.dt', function (e, dt, type, indexes){
var countSelectedRows = myProductGapsTable.rows( {selected: true} ).count()
var countItems = myProductGapsTable.rows().count()
if (countItems > 0) {
console.log("~ countItems > 0")
if (countSelectedRows == countItems){
$('thead .selectall-checkbox input[type="checkbox"]', this).prop('checked', true);
} else {
$('thead .selectall-checkbox input[type="checkbox"]', this).prop('checked', false);
}
}
if (e.type === 'select') {
$('.selectall-checkbox input[type="checkbox"]', myProductGapsTable.rows({search: 'applied', selected: true}).nodes()).prop('checked', true);
} else {
$('.selectall-checkbox input[type="checkbox"]', myProductGapsTable.rows({selected: false}).nodes()).prop('checked', false);
}
});
// When clicking on "thead .selectall-checkbox", trigger click on checkbox in that cell.
myProductGapsTable.on('click', 'thead .selectall-checkbox', function() {
$('input[type="checkbox"]', myProductGapsTable.rows({ search: 'applied', selected: true })).trigger('click');
});
// When clicking on the checkbox in "thead .selectall-checkbox", define the actions.
myProductGapsTable.on('click', 'thead .selectall-checkbox input[type="checkbox"]', function(e) {
if (this.checked) {
myProductGapsTable.rows({ search: 'applied' }).select();
} else {
myProductGapsTable.rows({ search: 'applied'}).deselect();
}
e.stopPropagation();
});
'select.dt deselect.dt' will be triggered when you click the select-all checkbox. And countItems is NOT the count of filtered item but the all items. so you should change countItems to myProductGapsTable.rows({search: 'applied'}).count() as below:
var countItems = myProductGapsTable.rows({search: 'applied'}).count()
I am using Select2 JS and Datatables JS. The data is in JSON format. The data for one value should display as Animal & Veterinary. In JSON it appears as Animal \u0026amp; Veterinary. The Select2 filter displays it as Animal & Veterinary. How can I add a function to the JS below that will decode the Unicode? Below is a function that can work but I dont know how to add it to the JS below.
var title = 'Animal & Veterinary';
function stringToSlug (title) {
return title.toLowerCase().trim()
.replace(/&/g, 'and')
}
Below is the script. This is where I would like to pass the function into the filter. "select2config"
jQuery( document ).ready( function($) {
'use strict';
// Check condition first if the table class exists then run this init.
if ($('.lcds-datatable--advisory-committee-materials').length > 0) {
let pageClass = function () {
let el = $( 'ul.pagination' ).addClass('pagination-sm');
}
// define order of table's control element
let domStyling = "<'row'<'col-sm-12'lB>>" +
"<'row'<'col-sm-12'tr>>" +
"<'row'<'col-sm-5'i><'col-sm-7'p>>";
var otable9 = $('table.lcds-datatable--advisory-committee-materials').DataTable( {
// Sort of first date column descending.
order: [[0, 'desc']],
deferRender: true,
deferLoading: 50,
dom: domStyling,
ajax: {
"url": "/datatables-json/advisory-committee-materials-json",
//"url": "/sites/default/files/actest1.json",
"dataSrc": ""
},
processing: true,
columns: [
{ "data": "field_publish_date" }, // publish_date 0
{ "data": "title" }, // node title summary 1
{ "data": "field_site_structure" } // site_structure Committee/Topic 2
],
columnDefs: [
{
"type": "date",
"targets": [ 0 ]
}
],
pageLength: 10,
searching: true,
autoWidth: false,
responsive: true,
lengthMenu: [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]],
buttons: [
{
extend: 'excel',
text: 'Export Excel',
exportOptions: {
columns: [ 0, 1, 2 ]
}
}
],
initComplete: pageClass,
drawCallback: pageClass
}); // end datatable
// config and initialize filters
let select2config = {
maximumSelectionLength: 0,
minimumInputLength: 0,
tags: true,
selectOnClose: true,
theme: "bootstrap",
}
let search = $( '#lcds-datatable-filter--search' ).lcdsTableFilter({
table: otable9,
type: 'search'
});
let clear = $( '#lcds-datatable-filter--clear' ).lcdsTableFilter({
table: otable9,
type: 'clear'
});
// wait for ajax call to complete to load column data load
$('table.lcds-datatable--advisory-committee-materials').on( 'init.dt', function() {
let committee = $( '#lcds-datatable-filter--committee-topic' ).lcdsTableFilter({
column: 2,
table: otable9,
select2Options: select2config,
type: 'select',
dataType: 'datatable'
});
})
}}); // end ready function and condition if the table class exists.
I was able to pass in a function to alter the output of JSON so now the filter displays “Animal & Veterinary” not “Animal & Veterinary” By adding this below. The filter now displays Animal & Veterinary but selecting this in the filter does not match the value in the datatable?
let select2config = {
maximumSelectionLength: 0,
minimumInputLength: 0,
tags: true,
selectOnClose: true,
theme: "bootstrap",
escapeMarkup: function (text) { return text; }
}
I have a datatable where it gets populated with data from the database. When the web page loads I call my Bind() function and this function populates the datatable with data as well as it initializes the datatable .
I also have a modal popup where users can add records. When they click the save button, it saves the record and I make an attempt to repopulate and reinitialize the data table.
The problem is that when I reinitialize the datatable the second time (on the button click), the datatable does not get reinitialized properly. It displays the headings after every record (see picture below). Please note that this only happens on the button click.
This my code so far:
$(document).ready(function () {
var dataTable;
Bind();
function Bind() {
$.ajax({
type: "POST",
url: "Clubs.aspx/GetCustomers",
data: '{}',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: OnSuccess,
failure: function (response) {
alert(response.d);
},
error: function (response) {
alert(response.d);
}
});
}
function OnSuccess(response) {
var xmlDoc = $.parseXML(response.d);
var xml = $(xmlDoc);
var customers = xml.find("Table");
var row = $("[id*=gvCustomers] tr:last-child").clone(true);
$("[id*=gvCustomers] tr").not($("[id*=gvCustomers] tr:first-child")).remove();
$.each(customers, function () {
var customer = $(this);
$("td", row).eq(0).html($(this).find("ClubID").text());
$("td", row).eq(1).html($(this).find("ClubName").text());
$("td", row).eq(2).html($(this).find("ClubEmail").text());
$("td", row).eq(3).html("<span>" + $(this).find("ClubID").text() + "</span>");
$("td", row).eq(4).html("<img id='btnID' src='/assets/img/edit.png' Style='width: 20px; height: 18px;'</>");
$("[id*=gvCustomers]").append(row);
row = $("[id*=gvCustomers] tr:last-child").clone(true);
});
//This is where I initializes my datatable
$('table').each(function () {
dataTable = $(this).prepend($("<thead style=background-color:#ff974d></thead>").append($(this).find("tr:eq(0)"))).DataTable({
"responsive": true,
"searching": true,
"aaSorting": [],
"sPaginationType": "full_numbers",
dom: 'lBfrtip',
buttons: [
{
extend: 'copy',
className: 'btn btn-success'
},
{
extend: 'excel',
text: 'Excel',
title: 'Centre Information',
className: 'btn btn-success',
orientation: 'portrait',
exportOptions: {
columns: [0, 1, 2]
}
},
{
extend: 'pdf',
text: 'PDF',
title: 'Centre Information',
className: 'btn btn-success',
orientation: 'portrait',
exportOptions: {
columns: [0, 1, 2]
}
},
{
extend: 'print',
text: 'PRINT',
title: 'Centre Information',
className: 'btn btn-success',
orientation: 'portrait',
exportOptions: {
columns: [0, 1, 2]
}
}
]
});
});
}
});
Then this is the code in the save button where I try to reinitialize the datatable
$("#btnSave").click(function () {
dataTable.destroy();
Bind();
return false;
});
Please assist how I can reinitialize the datatable correctly.
Try storing the DataTable in a variable and destroy that before rebinding the data.
So first create a varaible that can be accessed in both functions.
var dataTable;
function Bind() {
//rest of code
}
Then assign the correct table to the variable
dataTable = $(this).prepend($("<thead style=background-color:#ff974d></thead>").append($(this).find("tr:eq(0)"))).DataTable({
And then on that button click destroy that
$("#btnSave").click(function () {
dataTable.destroy();
Bind();
return false;
});
var specificatonsData = [];
function initGridForTransactions(gridID, gridPagerID) {
var grid_selector = gridID;
var pager_selector = gridPagerID;
$(window).on('resize.jqGrid', function () {
$(grid_selector).jqGrid('setGridWidth', $("#page-wrapper").width());
})
var parent_column = $(grid_selector).closest('[class*="col-"]');
$(document).on('settings.ace.jqGrid', function (ev, event_name, collapsed) {
if (event_name === 'sidebar_collapsed' || event_name === 'main_container_fixed') {
setTimeout(function () {
$(grid_selector).jqGrid('setGridWidth', parent_column.width());
}, 0);
}
})
$(grid_selector).jqGrid({
data: specificatonsData,
datatype: "local",
colNames: ['Id','Specification', 'Abbreviation'],
colModel: [
{ name: 'Id', width: 80,key:true },
{ name: 'specification', index: 'Id', key: true, width: 300 },
{ name: 'abbreviation', width: 300 },
],
cmTemplate: { editable: true },
cellsubmit: 'clientArray',
editurl: 'clientArray',
viewrecords: true,
rowNum: 4000,
gridview: true,
rowList: [4000],
pager: pager_selector,
altRows: true,
loadonce: true,
multiselect: false,
multiboxonly: false,
sortname: 'Specification',
sortorder: "asc",
cellEdit: false,
iconSet: "fontAwesome",
onSelectRow: function (rowId, status, e) {
var dealerFeatures = $("#editor").text();
var selectedFeature = rowId;
selectedFeature = selectedFeature.replace(/(\s+)/, "(<[^>]+>)*$1(<[^>]+>)*");
var pattern = new RegExp("(" + selectedFeature + ")", "gi");
dealerFeatures = dealerFeatures.replace(pattern, "<mark>$1</mark>");
//dealerFeatures = dealerFeatures.replace(/(<mark>[^<>]*)((<[^>]+>)+)([^<>]*<\/mark>)/, "$1<mark>$2</mark>$4");
dealerFeatures = dealerFeatures.replace(/(<mark>[<>]*)((<[>]+>)+)([<>]*<\/mark>)/, "$1<mark>$2</mark>$4");
dealerFeatures = dealerFeatures.replace(/\n/g, '<br>\n');
$("#editor").html(dealerFeatures);
},
gridComplete: function () {
$(grid_selector).setColProp('Approve', { editoptions: { value: '' } });
},
loadComplete: function () {
var table = this;
setTimeout(function () {
updatePagerIcons(table);
enableTooltips(table);
}, 0);
},
}).navGrid(pager_selector, { edit: true, add: true, del: false },
{
url: '/Activity/SaveSpecification',
closeAfterAdd: true,
closeAfterEdit: true,
afterSubmit: function () {
getAbbrData();
return [true, '', ''];
}
});
jQuery(grid_selector).sortableRows();
function updatePagerIcons(table) {
var replacement =
{
'ui-icon-seek-first': 'ace-icon fa fa-angle-double-left bigger-140',
'ui-icon-seek-prev': 'ace-icon fa fa-angle-left bigger-140',
'ui-icon-seek-next': 'ace-icon fa fa-angle-right bigger-140',
'ui-icon-seek-end': 'ace-icon fa fa-angle-double-right bigger-140'
};
$('.ui-pg-table:not(.navtable) > tbody > tr > .ui-pg-button > .ui-icon').each(function () {
var icon = $(this);
var $class = $.trim(icon.attr('class').replace('ui-icon', ''));
if ($class in replacement) icon.attr('class', 'ui-icon ' + replacement[$class]);
})
}
function enableTooltips(table) {
$('.navtable .ui-pg-button').tooltip({ container: 'body' });
$(table).find('.ui-pg-div').tooltip({ container: 'body' });
}
$(document).one('ajaxloadstart.page', function (e) {
$(grid_selector).jqGrid('GridUnload');
$('.ui-jqdialog').remove();
});
}
I will save data to database only when I click on external Submit button.
When I click on edit button the data is showing in a popup and when I click on the save button the data is getting to the database and showing in the jqgrid.
But I have a new requirement where I have to show the data in the jqgrid when click on save button but should not save to the database.
Thanks in advance.
If you use Guriddo jqGrid JS then you can set url in edit options in your navigator to be clientArray - i.e
...navGrid(pager_selector, { edit: true, add: true, del: false },
{
url: 'clientArray',
closeAfterAdd: true,
closeAfterEdit: true,
afterSubmit: function () {
getAbbrData();
return [true, '', ''];
}
});
This will save the data locally.
The code, which you posted contains many small bugs. For example,
you use url: '/Activity/SaveSpecification' as form Edit options (not for Add form) - see navGrid call. You should remove the option to make editurl: 'clientArray' working
you use key:true in more as one column. It's not allowed. One can use it only in one column, which contains unique values.
the usage of index: 'Id' property in colModel for the column name: 'specification' is probably one more bug, which can make wrong sorting and filtering in the column.
your current code contains call of .setColProp('Approve', { ... });, which is wrong, because your colModel don't contains the column 'Approve'
the option sortname: 'Specification' is wrong too, because the value of sortname should be the value of name property from colModel (like sortname: 'specification' for example, if you'll remove index: 'Id' property from the column).
Additionally the usage of rowNum: 4000 can essentially reduce the performance of the grid in case of large grid. If real number of rows is about 4000, then it's much more effective to use local paging of data. The monitor allows to display only about 20-25 rows. Thus it's recommended to use pager with such small rowNum. Users can use paging buttons to go to the next page.
Hi I have a Grid that is using cell edit and Inline editing. It saves to the ClientArray
$('#list').jqGrid({
datatype: "local",
colNames: ["Parameter Id", "Parameter Name", 'Parameter Value'],
colModel: [
{ name: "Id", index: "Id", align: "left", key: true, editable: false,hidden:true, jmap: 0 },
{ name: "ParameterName", index: "ParameterName", align: "left", editable: false, jmap: 1 },
{ name: "ParameterValue", index: "ParameterValue", align: "left", editable: true, edittype: "text", editoptions: { maxlength: 100 }, editrules: {required: true }, jmap: 2 }
],
pager: "#pager",
rowNum: 100,
rowList: [],
pgbuttons: false, // disable page control like next, back button
pgtext: null, // disable pager text like 'Page 0 of 10'
viewrecords: true, // disable current view record text like 'View 1-10 of 100'
height: '100%',
scrollOffset: 0,
sortname: "Name",
sortorder: "Asc",
gridview: true,
caption: 'Parameters',
autowidth: true,
hidegrid: false,
loadonce: true,
//beforeEditCell: function () {
// $("#list_ilsave").removeClass('ui-state-disabled');
// return;
//},
//afterEditCell: function (rowid, cellname, value, iRow, iCol) {
// $('#list').jqGrid('getCell', rowid, iCol).focus();
// return;
//},
width: totalWidth,
cellEdit: true,
cellsubmit: "clientArray"
});
$('#list').jqGrid('inlineNav', '#pager', {
edit: false,
add: false,
del: false,
save: true,
savetext: 'Save',
cancel: false
});
When I edit a Cell the save button remains disabled. If I manually Enable the button in beforeCellEdit, the editable cell hasn't got focus until you select another cell. This behavior is only happening in IE.
I have tried to fix both these issues individually in my commented out code, and I have found that the loss of focus is caused by the line
$("#list_ilsave").removeClass('ui-state-disabled');
I tried placing this line in beforeEditCell and in afterEditCell and it causes the input field to loose focus.
I was using JQ Grid 4.4.4 and I have tried updating to 4.6.0 after I read there were updates to Inline Editing after 4.4.4
UPDATE
I have changed my grid to use onSelectRow
onSelectRow: function (rowid) {
var $grid = $('#list');
var iRow = $("#" + rowid)[0].rowIndex;
$grid.jqGrid('editRow', rowid, {
keys: true,
oneditfunc: function(rowid, response) {
var $saveButton = $("#list_ilsave");
if ($saveButton.hasClass('ui-state-disabled')) {
$saveButton.removeClass('ui-state-disabled');
}
markCellAsDirty(rowid, $grid);
return true;
},
successfunc: function() {
alert('success');
return true;
},
aftersavefunc: function() {
alert('after save');
return true;
},
errorfunc: function() {
alert('error');
return true;
}
});
},
cellsubmit: "clientArray"
But I can't get any of the editRow events to fire other than oneditfunc. I also have an issue with getting the changed cells.
This method marks the cells as dirty / edited
function markCellAsDirty(rowid, grid) {
$(grid.jqGrid("setCell", rowid, "ParameterValue", "", "dirty-cell"));
$(grid[0].rows.namedItem(rowid)).addClass("edited");
}
I try to get the edited cells as follows
var editedRows = $grid.getChangedCells('dirty');
Before posting editedRows in an AJAX method to my server.
I'm not sure what you want to implement exactly, but I modified your demo to the following https://jsfiddle.net/OlegKi/byygepy3/11/. I include the full JavaScript code of the demo below
$(function () {
var myData = [
{ id: 10, ParameterName: "Test", ParameterValue: "" },
{ id: 20, ParameterName: "Test 1", ParameterValue: "" },
{ id: 30, ParameterName: "Test 2", ParameterValue: "" }
],
$grid = $("#list");
// change the text displayed on editrules: {required: true }
$.extend(true, $.jgrid.locales["en-US"].edit.msg, {
required: "No value was entered for this parameter!!!"
});
$grid.jqGrid({
datatype: "local",
data: myData,
colNames: ["", "Parameter Name", "Parameter Value"],
colModel: [
{ name: "act", template: "actions" }, // optional feature
{ name: "ParameterName" },
{ name: "ParameterValue", editable: true,
editoptions: { maxlength: 100 }, editrules: {required: true } }
],
cmTemplate: { autoResizable: true },
autoResizing: { compact: true },
pager: true,
pgbuttons: false, // disable page control like next, back button
pgtext: null, // disable pager text like 'Page 0 of 10'
viewrecords: true, // disable current view record text like 'View 1-10 of 100'
sortname: "Name",
iconSet: "fontAwesome",
caption: 'Parameters',
autowidth: true,
hidegrid: false,
inlineEditing: {
keys: true
},
singleSelectClickMode: "selectonly", // prevent unselect once selected rows
beforeSelectRow: function (rowid) {
var $self = $(this), i,
// savedRows array is not empty if some row is in inline editing mode
savedRows = $self.jqGrid("getGridParam", "savedRow");
for (i = 0; i < savedRows.length; i++) {
if (savedRows[i].id !== rowid) {
// save currently editing row
// one can replace saveRow to restoreRow in the next line
$self.jqGrid("saveRow", savedRows[i].id);
}
}
return savedRows.length === 0; // allow selection if saving successful
},
onSelectRow: function (rowid) {
$(this).jqGrid("editRow", rowid);
},
afterSetRow: function (options) {
var item = $(this).jqGrid("getLocalRow", options.rowid);
if (item != null) {
item.dirty = true;
}
},
navOptions: {
edit: false,
add: false,
search: false,
deltext: "Delete",
refreshtext: "Refresh"
},
inlineNavOptions: {
save: true,
savetext: "Save",
cancel: false,
restoreAfterSelect: false
},
formDeleting: {
// delete options
url: window.g_baseUrl + 'MfgTransactions_MVC/COA/Delete?',
beforeSubmit: function () {
// get value
var selRowId = $(this).jqGrid('getGridParam', 'selrow');
var parametricValue = $(this).jqGrid('getCell', selRowId, 'ParameterValue');
// check if empty
if (parametricValue === "") {
return [false, "Cannot delete: No value exists for this parameter"];
}
return [true, "Successfully deleted"];
},
delData: {
batchId: function () {
return $("#BatchId").val();
}
},
closeOnEscape: true,
closeAfterDelete: true,
width: 400,
msg: "Are you sure you want to delete the Parameter?",
afterComplete: function (response) {
if (response.responseText) {
alert("response.responseText");
}
//loadBatchListIntoGrid();
}
}
}).jqGrid('navGrid')
.jqGrid('inlineNav')
.jqGrid('navButtonAdd', {
caption: "Save Changed",
buttonicon: "fa-floppy-o",
onClickButton: function () {
var localData = $(this).jqGrid("getGridParam", "data"),
dirtyData = $.grep(localData, function (item) {
return item.dirty;
});
alert(dirtyData.length > 0 ? JSON.stringify(dirtyData) : "no dirty data");
}
});
// make more place for navigator buttons be rwducing the width of the right part
var pagerIdSelector = $grid.jqGrid("getGridParam", "pager");
$(pagerIdSelector + "_right").width(100);
// make the grid responsive
$(window).bind("resize", function () {
$grid.jqGrid("setGridWidth", $grid.closest(".container-fluid").width());
}).triggerHandler("resize");
});
where HTML code is
<div class="container-fluid">
<div class="row">
<div id="gridarea" class="col-md-6 col-md-offset-3">
<table id="list"></table>
</div>
</div>
</div>
and CSS code
.ui-th-column>div, .ui-jqgrid-btable .jqgrow>td {
word-wrap: break-word; /* IE 5.5+ and CSS3 */
white-space: pre-wrap; /* CSS3 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
overflow: hidden;
vertical-align: middle;
}
It demonstrate how one can implement starting inline editing on select row. Additionally I added optional column with template: "actions" which can be alternative implementation. I set property dirty in every item of data inside of afterSetRow callback and I added "Save Changed" button, which uses localData = $(this).jqGrid("getGridParam", "data") and dirtyData = $.grep(localData, function (item) { return item.dirty; }); to get the dirty (modified) data.