Append element to Datatable header - javascript

What I'd like to do is add a radio button next to the Search Bar on my datatable to allow searching by just one column, Store Number.
I was referred to drawCallback but I don't believe this does what I expect it to do. All the answers I find seem to be appending elements to rows/cols in the datatable, but not the header itself.
The selector for this header is #store-table_wrapper.
$('#store-table').DataTable({
"columnDefs": [{
"targets": [7, 8],
"visible": false,
"drawCallback": function() {
$('<input type="radio" name="store-number-filter-selector" />').appendTo('#store-table_wrapper');
}
}]
});

I believe, getting your radio button displayed you're half-way through, the really challenging part is to disable default search bar, since you're unlikely to override its default behavior (to search through the entire table).
However, you may use your own, custom searchbar, like on the following DEMO:
//define source data
const srcData = [
{id: 1, name: 'apple', category: 'fruit'},
{id: 2, name: 'raspberry', category: 'berry'},
{id: 3, name: 'carrot', category: 'vegie'}
];
//define dataTable object
const dataTable = $('#mytable').DataTable({
sDom: 't',
data: srcData,
columns: [
{data: 'id', title: 'id'},
{data: 'name', title: 'name'},
{data: 'category', title: 'category'}
],
//modify header nodes, by appending radios
initComplete: function() {
const table = this.api();
[1,2].forEach(column => table.column(column).header().innerHTML += `<input type="radio" name="searchflag" value="${column}" class="searchflag"></input>`);
}
});
//prevent sorting change upon radio click
$('input.searchflag').on('click', function(event) {
//clear search upon choosing the other radio
$('#searchfield').val('');
dataTable.search('').columns().search('').draw();
event.stopPropagation();
});
//searchbar keyup callback
$('#searchfield').on('keyup', function() {
//grab checked radio button value or search the entire table by default
let targetColumn = null;
targetColumn = $('input.searchflag:checked').val();
if(!targetColumn){
dataTable.search($(this).val()).draw();
}
else {
dataTable.column(targetColumn).search($(this).val()).draw();
}
})
input.searchflag {
float: left;
}
<!doctype html>
<html>
<head>
<script type="application/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="application/javascript" src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="demo.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css">
</head>
<body>
<input id="searchfield"></input>
<table id="mytable"></table>
</body>
</html>

Related

Kendo Grid UI: Enable custom text copy with multiple row select feature

I am having a kendo grid where the multiple row selection is enabled. With multiple selection functionality, when users try to copy custom text like any value from the column, it enables multiple select features thus users cannot copy custom text.
Below is the sample:
https://dojo.telerik.com/#erpuneet507/ivAfoFup
The issue is, in the above example you can select text from a single cell/ or any partial text from the cell.
If you have multiple selection enabled, then your app has to handle the copy text to clipboard. In doing so, you'll need the clipboard.js library and add a Kendo ContextMenu. Handle the copy text in the ContextMenu select event. Copy Text should pop up on right click.
Try the code below in the Telerik DOJO:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Kendo UI Snippet</title>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2021.2.616/styles/kendo.default-v2.min.css"/>
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2021.2.616/js/kendo.all.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.7.1/clipboard.min.js"></script>
</head>
<body>
<div id="grid"></div>
<ul id="context-menu">
<li id="copyText">Copy Text</li>
</ul>
<script>
$(document).ready(function() {
$("#grid").kendoGrid({
selectable: "multiple row",
allowCopy: true,
columns: [
{ field: "productName" },
{ field: "category" }
],
dataSource: [
{ productName: "Tea", category: "Beverages" },
{ productName: "Coffee", category: "Beverages" },
{ productName: "Ham", category: "Food" },
{ productName: "Bread", category: "Food" }
]
});
$("#context-menu").kendoContextMenu({
target: "#grid",
filter: "td",
select: function (e) {
var cell = e.target;
var row = $(cell).parent()[0];
var grid = $("#grid").data("kendoGrid");
var itemId = e.item.id;
var cellText = cell.innerText;
if (itemId === 'copyText') {
new Clipboard('#copyText', {
text: function (trigger) {
return cellText;
}
});
};
}
});
});
</script>
</body>
</html>
Here's a revised version of the above. You'll no longer need the clipboard.js. This will show/pop up the text (e.g. coffee) when you right click so that you can copy the 'ffee'.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Kendo UI Snippet</title>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2021.2.616/styles/kendo.default-v2.min.css"/>
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2021.2.616/js/kendo.all.min.js"></script>
</head>
<body>
<div id="grid"></div>
<ul id="context-menu">
<li id="copyText">
<input id="valueText"></input>
<span id="closeValueText" class="k-icon k-i-close"></span>
</li>
</ul>
<script>
$(document).ready(function() {
$("#grid").kendoGrid({
selectable: "multiple row",
allowCopy: true,
columns: [
{ field: "productName" },
{ field: "category" }
],
dataSource: [
{ productName: "Tea", category: "Beverages" },
{ productName: "Coffee", category: "Beverages" },
{ productName: "Ham", category: "Food" },
{ productName: "Bread", category: "Food" }
]
});
var closeContextMenu = false;
var contextMenu = $("#context-menu").kendoContextMenu({
target: "#grid",
filter: "td",
close: function(e) {
if (!closeContextMenu) {
e.preventDefault();
}
},
open: function(e) {
var cell = e.target;
var row = $(cell).parent()[0];
var grid = $("#grid").data("kendoGrid");
var itemId = e.item.id;
var cellText = cell.innerText;
$(e.item).find("#valueText").val(cellText);
closeContextMenu = false;
}
}).data("kendoContextMenu");
$("#closeValueText").on("click", function(e) {
closeContextMenu = true;
contextMenu.close();
});
});
</script>
</body>
</html>

How to display a confirmation Modal with columns data on button click using Datatables

Having the DataTable below, I would like to display a dynamic popup or modal whenever a button is clicked which will serve as a confirmation modal.
The modal should contain data coming from the columns in the respected row in which the button was clicked.
#section scripts
{
<script>
$(document).ready(function() {
var table = $('#visitorsTable').DataTable({
"ajax": {
...
},
"columns": [
{ "data": "FirstName" },
{ "data": "LastName" },
{ "data": "Email" },
{ "data": "PhoneNumber" },
{ "data": "WifiCode" },
],
columnDefs: [
{
targets: [4],
render: function(wifiCode, b, data, d) {
if (wifiCode) {
var content = '<span>' + wifiCode + '</span>';
if (data.Email && data.PhoneNumber) {
content +=
'<button type="button" class="btnResendByMail>Email</button>'
return content;
}
}
}
]
});
$(document).on('click',
'.btnResendByMail',
function() {
$.ajax({
....
});
});
});
</script>
}
I've seen on DataTables site the "responsive" plugin.
However, on their example the modal is triggered always by clicking on the first column, and they display all the data of the row, not specific columns.
Any idea ?
...if I got your question properly, I believe, that's what you're trying to achieve:
srcData = [
{name: 'Albert', lastname: 'Einstein', email: 'emc2#gmail.com', code: 'XOIUE#WL'},
{name: 'Nikola', lastname: 'Tesla', email: 'firebolt#hotmail.com', code: 'OUWelks'},
{name: 'Rudolf', lastname: 'Hertz', email: 'radiohead#yahoo.com', code: 'joi23.xs'},
{name: 'James', lastname: 'Maxwell', email: 'magneto#gmail.com', code: 'Moiu23s'},
];
var dataTable = $('#mytable').DataTable({
sDom: 't',
data: srcData,
columns: [
{title: 'Name', data: 'name'},
{title: 'Lastname', data: 'lastname'},
{title: 'e-mail', data: 'email'},
{
title: 'Wi-Fi code',
data: 'code',
render: (data) => data+'<button style="float:right">e-mail</button>'
}
]
});
$('#mytable').on('click', 'button', event => {
let rowData = dataTable.row($(event.target).closest('tr')).data();
alert(`Are you sure you wanna send wi-fi code "${rowData.code}" to that sneaky bastard ${rowData.name} on his e-mail (${rowData.email})?`);
});
<!doctype html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css">
</head>
<body>
<table id="mytable"></table>
</body>
</html>

How do I achieve jQuery DataTables colspan with striping after sorting?

Details follow, but the question is:
Is there a recommended best practice for using colspan / child rows with jQuery DataTables that is compatible with sorting and uses the same row coloring as the parent row?
Constraint (non negotiable):
My client wants a sortable table that includes multiple child rows that span the entire table.
Some of the colspan rows exist only if there is data to support them.
(Thank you in advance for your comments such as "colspan is horrible!" and "tables are gross!" but they are not helpful here.)
Attempted solution
I am using jQuery DataTables, which is a rad library for progressive enhancement and scripted generation of HTML tables. Note that on this website Javascript is required, and I opted to create the table dynamically via Javascript rather than to render HTML table and enhance it.
I was able to achieve the colspan effect by using the row().child() feature documented here.
The client requires the child rows to have the same row striping color as the parent row, and to not look indented. DataTables assigns odd and even class names to each TR element (rather than using nth-child() CSS selectors), which is actually helpful in this case because I can use the same CSS class (odd or even) to style the child rows.
However, I ran into a style problem when sorting because the child rows persist (are not regenerated) upon order operations. The result looks kinda bad, and requires an even number of rows to observe. (Run snippet, and click on the Name column to see the problem)
var rows = [{
ID: 1,
Name: "Bob",
Comments: "Bob is a hard worker"
}, {
ID: 2,
Name: "Ann",
Comments: "Ann takes a lot of smoke breaks"
}, {
ID: 3,
Name: "Carl",
Comments: "Carl needs some serious help"
}, {
ID: 4,
Name: "Dave",
Comments: "Dave is a rockstar",
Extra: "Extra comments go here"
}];
var columns = [{
name: 'id',
data: 'ID',
title: 'ID',
orderable: true
}, {
name: 'name',
data: 'Name',
title: 'Name',
orderable: true
}];
var tableOptions = {
data: rows,
columns: columns,
info: false,
paging: false,
processing: false,
searching: false,
};
var dataTable = $("#t").DataTable(tableOptions);
var rows = dataTable.rows()[0];
$.each(rows, function (idx, rowIdx) {
var row = dataTable.row(rowIdx);
var rowData = row.data();
var cssClass = idx % 2 === 0 ? 'odd' : 'even'; // in DT-speak, first body row is even (not odd)
var childRows = [];
childRows.push(rowData.Comments);
if (rowData.Extra) {
childRows.push(rowData.Extra);
}
row.child(childRows, cssClass).show();
});
table.dataTable thead tr {
background-color: #ccc;
}
table.dataTable tbody tr.odd {
background-color: #DAE4F0;
}
table.dataTable tbody tr.even {
background-color: #eeeeee;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="http://cdn.datatables.net/1.10.6/css/jquery.dataTables.css" rel="stylesheet"/>
<script src="http://cdn.datatables.net/1.10.6/js/jquery.dataTables.min.js"></script>
<table id='t'></table>
Attempted solution, take 2
I added an event handler to fix the CSS classes on child rows when the order event fires on the DataTable using dataTable.on('order.dt', function(){...})
This works, but feels clunky, like I am abusing the row().child() concept maybe. Maybe not. Does anybody know of a better way? (Run snippet below for the "fixed" example).
var rows = [{
ID: 1,
Name: "Bob",
Comments: "Bob is a hard worker"
}, {
ID: 2,
Name: "Ann",
Comments: "Ann takes a lot of smoke breaks"
}, {
ID: 3,
Name: "Carl",
Comments: "Carl needs some serious help"
}, {
ID: 4,
Name: "Dave",
Comments: "Dave is a rockstar",
Extra: "Extra comments go here"
}];
var columns = [{
name: 'id',
data: 'ID',
title: 'ID',
orderable: true
}, {
name: 'name',
data: 'Name',
title: 'Name',
orderable: true
}];
var tableOptions = {
data: rows,
columns: columns,
info: false,
paging: false,
processing: false,
searching: false,
};
var dataTable = $("#t").DataTable(tableOptions);
var rows = dataTable.rows()[0];
$.each(rows, function (idx, rowIdx) {
var row = dataTable.row(rowIdx);
var rowData = row.data();
var cssClass = idx % 2 === 0 ? 'odd' : 'even'; // in DT-speak, first body row is even (not odd)
var childRows = [];
childRows.push(rowData.Comments);
if (rowData.Extra) {
childRows.push(rowData.Extra);
}
row.child(childRows, cssClass).show();
});
dataTable.on('order.dt', function () {
var rows = dataTable.rows()[0];
$.each(rows, function (idx, rowIdx) {
var row = dataTable.row(rowIdx);
var childRows = row.child();
childRows.removeClass("even odd");
var cssClass = idx % 2 === 0 ? 'odd' : 'even'; // in DT-speak, first body row is even (not odd)
childRows.addClass(cssClass);
});
});
table.dataTable thead tr {
background-color: #ccc;
}
table.dataTable tbody tr.odd {
background-color: #DAE4F0;
}
table.dataTable tbody tr.even {
background-color: #eeeeee;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="http://cdn.datatables.net/1.10.6/css/jquery.dataTables.css" rel="stylesheet"/>
<script src="http://cdn.datatables.net/1.10.6/js/jquery.dataTables.min.js"></script>
<table id='t'></table>
Thanks for reading!
Am I making it harder than it is? Is this the only way to achieve my solution using jQuery DataTables? Is there perhaps a different library that is similar but has better out-of-box support for colspan?
Here is same example in JSFiddle if you prefer: http://jsfiddle.net/h57vjof6/3/

Getting most basic Backgrid.js example working

I am trying to get the most basic example of backgrid.js to work. In other words, an example where i can drop the source folder into my xampp/htdocs folder and run without having to do anything else.
I have tried many ways to get the code to run but i cannot get anything to show up.
Here is the html page i made to try to see an example working.
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="bootstrap/css/bootstrap.css"/>
<link rel="stylesheet" href="lib/backgrid.css"/>
<script src="jquery-1.10.2.min.js"></script>
<script src="underscore-min.js"></script>
<script src="backbone-min.js"></script>
<script src="lib/backgrid.js"></script>
</head>
<body>
<div id="grid">
<script type="text/javascript">
var Territory = Backbone.Model.extend({});
var Territories = Backbone.Collection.extend({
model: Territory,
url: "territories.json"
});
var territories = new Territories();
var columns = [{
name: "id", // The key of the model attribute
label: "ID", // The name to display in the header
editable: false, // By default every cell in a column is editable, but *ID* shouldn't be
// Defines a cell type, and ID is displayed as an integer without the ',' separating 1000s.
cell: Backgrid.IntegerCell.extend({
orderSeparator: ''
})
}, {
name: "name",
label: "Name",
// The cell type can be a reference of a Backgrid.Cell subclass, any Backgrid.Cell subclass instances like *id* above, or a string
cell: "string" // This is converted to "StringCell" and a corresponding class in the Backgrid package namespace is looked up
}, {
name: "pop",
label: "Population",
cell: "integer" // An integer cell is a number cell that displays humanized integers
}, {
name: "percentage",
label: "% of World Population",
cell: "number" // A cell type for floating point value, defaults to have a precision 2 decimal numbers
}, {
name: "date",
label: "Date",
cell: "date"
}, {
name: "url",
label: "URL",
cell: "uri" // Renders the value in an HTML anchor element
}];
// Initialize a new Grid instance
var grid = new Backgrid.Grid({
columns: columns,
collection: territories
});
// Render the grid and attach the root to your HTML document
$("#example-1-result").append(grid.render().el);
// Fetch some countries from the url
territories.fetch({reset: true});
</script>
</div>
</body>
</html>
Thanks for your time!
You seem to be adding the grid to non-existing element:
$("#example-1-result").append(grid.render().el);
Use $("#grid") instead and you should see the result.

JQWidgets jqxGrid with jqxDropDownList as editor

Could someone provide the proper implementation method for utilizing the jqxDropDownList with checkboxes enabled as a grid column?
The following code is modified from the jqwidgets grid demo code ‘cellediting.htm’.
I've implemented an independent dropdownlist with checkboxes with no problems.
I've implemented a grid with dropdownlist (with out checkboxes) with no problems.
however, as soon as i put checkboxes: true in the initeditor i get the following error:
Uncaught TypeError: Cannot read property ‘instance’ of undefined jqxlistbox.js:7
In certain ‘more complicated’ scenarios, the checkboxes property will succeed with ‘createeditor’, but fail with initeditor.
This leads me to believe there is probably some asynchronous loading going on and im building the editor too quickly.
The following code fails because of the ‘checkboxes: true’ property. remove that and it works great.
<head>
<title id='Description'>In order to enter in edit mode, select a grid cell and start typing, "Click" or press the "F2" key. You
can also navigate through the cells using the keyboard arrows or with the "Tab" and "Shift + Tab" key combinations. To cancel the cell editing, press the "Esc" key. To save
the changes press the "Enter" key or select another Grid cell. Pressing the 'Space' key when a checkbox cell is selected will toggle the check state.</title>
<link rel="stylesheet" href="../../jqwidgets/styles/jqx.base.css" type="text/css" />
<script type="text/javascript" src="../../scripts/jquery-1.8.3.min.js"></script>
<script type="text/javascript" src="../../jqwidgets/jqxcore.js"></script>
<script type="text/javascript" src="../../jqwidgets/jqxdata.js"></script>
<script type="text/javascript" src="../../jqwidgets/jqxbuttons.js"></script>
<script type="text/javascript" src="../../jqwidgets/jqxscrollbar.js"></script>
<script type="text/javascript" src="../../jqwidgets/jqxmenu.js"></script>
<script type="text/javascript" src="../../jqwidgets/jqxgrid.js"></script>
<script type="text/javascript" src="../../jqwidgets/jqxgrid.edit.js"></script>
<script type="text/javascript" src="../../jqwidgets/jqxgrid.selection.js"></script>
<script type="text/javascript" src="../../jqwidgets/jqxgrid.filter.js"></script>
<script type="text/javascript" src="../../jqwidgets/jqxlistbox.js"></script>
<script type="text/javascript" src="../../jqwidgets/jqxdropdownlist.js"></script>
<script type="text/javascript" src="../../jqwidgets/jqxcheckbox.js"></script>
<script type="text/javascript" src="../../jqwidgets/jqxcalendar.js"></script>
<script type="text/javascript" src="../../jqwidgets/jqxnumberinput.js"></script>
<script type="text/javascript" src="../../jqwidgets/jqxdatetimeinput.js"></script>
<script type="text/javascript" src="../../jqwidgets/globalization/globalize.js"></script>
<script type="text/javascript" src="../../scripts/gettheme.js"></script>
<script type="text/javascript" src="generatedata.js"></script>
<script type="text/javascript">
$(document).ready(function () {
// prepare the data
var data =
[
{ firstname: 'joe', lastname: 'smith', sex: 'm' },
{ firstname: 'john', lastname: 'doe', sex: 'm' },
{ firstname: 'jane', lastname: 'doe', sex: 'f' }
];
var source =
{
localdata: data,
datatype: "array",
updaterow: function (rowid, rowdata, commit) {
commit(true);
},
datafields:
[
{ name: 'firstname', type: 'string' },
{ name: 'lastname', type: 'string' },
{ name: 'sex', type: 'string' }
]
};
var dataAdapter = new $.jqx.dataAdapter(source);
// initialize jqxGrid
$("#jqxgrid").jqxGrid(
{
width: 685,
source: dataAdapter,
editable: true,
selectionmode: 'multiplecellsadvanced',
columns: [
{ text: 'First Name', columntype: 'textbox', datafield: 'firstname', width: 80 },
{ text: 'Last Name', columntype: 'textbox', datafield: 'lastname', width: 80 },
{ text: 'Sex', columntype: 'dropdownlist', datafield: 'sex', width: 195,
createeditor: function(row, cellvalue, editor)
{
var mydata =
[
{ value: "m", label: "Male" },
{ value: "f", label: "Female" }
];
var mysource =
{
datatype: "array",
datafields:
[
{ name: 'label', type: 'string' },
{ name: 'value', type: 'string' }
],
localdata: mydata
};
var myadapter = new $.jqx.dataAdapter(mysource, { autoBind: true });
editor.jqxDropDownList({ checkboxes: true, source: myadapter, displayMember: 'label', valueMember: 'value' });
}
}
]
});
// events
$("#jqxgrid").on('cellbeginedit', function (event) {
var args = event.args;
$("#cellbegineditevent").text("Event Type: cellbeginedit, Column: " + args.datafield + ", Row: " + (1 + args.rowindex) + ", Value: " + args.value);
});
$("#jqxgrid").on('cellendedit', function (event) {
var args = event.args;
$("#cellendeditevent").text("Event Type: cellendedit, Column: " + args.datafield + ", Row: " + (1 + args.rowindex) + ", Value: " + args.value);
});
});
</script>
</head>
<body class='default'>
<div id='jqxWidget'>
<div id="jqxgrid"></div>
<div style="font-size: 12px; font-family: Verdana, Geneva, 'DejaVu Sans', sans-serif; margin-top: 30px;">
<div id="cellbegineditevent"></div>
<div style="margin-top: 10px;" id="cellendeditevent"></div>
</div>
</div>
</body>
</html>
Can anyone offer assistance?
Extra help!!
Additionally, it seems like once i select a value in the dropdown, the actual ‘value’ gets changed to the display ‘label’. i.e., (“Male” or “Female”), but in this example, the only valid data for the sex field would be ‘m’ or ‘f’.
I've asked the same question on the jqwidgets official forums (here: http://www.jqwidgets.com/community/topic/dropdownlist-with-checkboxes-as-grid-column-editor/), and will post any answer they send here if they beat the community to it.
As far as I know, there is no DropDownList with Checkboxes Editor in the jQwidgets Grid. If there was such, I think that jQWidgets would at least have a sample about it so I suppose that you cannot use the DropDownList in such way in the jqxGrid widget.
I know that this is a rather old post, but still...
I'm surprised to see the response from the JQWidgets team, since they themselves have such an example on their website, using a dropdownlist with checkboxes as a grid editor.
It is available at http://www.jqwidgets.com/jquery-widgets-demo/demos/jqxgrid/index.htm#demos/jqxgrid/cellcustomediting.htm
where the editor is used in the Products column.
Mihai

Categories