Parameter Not Passing in jquery dataTable Ajax Call - javascript

I have written a code to display the dynamic table into DataTable.
<table id="tag" class="display table table-striped table-bordered" cellspacing="0" width="100%">
<thead>
<tr>
#foreach (var item in Model.HeaderModelList.Select((value, i) => new { i, value }))
{
<th id=#(item.i+1)>
#item.value.Category
<span class="filterExcel">
<select id="tag#(item.value.PatientTagCategoryId)" name="tag" asp-items="#item.value.HeaderOptions" multiple class="drp-tagMulti-Select">
</select>
</span>
</th>
}
<th id="#(Model.HeaderModelList.Count()+1)">Simulation Name
</th>
<th id="#(Model.HeaderModelList.Count()+2)">
Patient Name
</th>
</tr>
</thead>
</table>
On changing the drop-down I have called an event that calls reload jquery.
$(document).ready(function () {
var id = "";
var newval = "";
$('.drp-tagMulti-Select').on('change', function () {
var valid = this.id;
var val = $('#' + valid).val();
if (valid) {
newval = val;
id = valid;
console.log("id" + id);
console.log("newval" + newval);
table.ajax.reload();
}
});
var table = $("#tag").DataTable({
"aLengthMenu": [[10, 25, 50, 75, -1], [10, 25, 50, 75, "All"]],
"iDisplayLength": 10,
"serverSide": true,
"processing": true,
"stateSave": true,
"search": true,
"ajax": {
'type': 'POST',
'dataType': 'json',
'data': {
TagId: id,
Values: newval
},
'url': 'GetFilteredPatientTags',
'dataSrc': function (d) {
var values = [];
for (var i = 0; i < d.data.length; i++) {
var result = Object.values(d.data[i]);
values.push(result);
}
return values;
}
}
});
$(".filterExcel").click(function (e) {
e.stopPropagation();
})
$('.drp-tagMulti-Select').multipleSelect({
placeholder: 'Select specific course',
ellipsis: true,
filter: true,
filterAcceptOnEnter: true,
animate: 'fade',
width: 20
})
$('.ms-drop').width('fit-content')
});
Now whenever I change the dropdown the event is triggered and the values of id and newval is displayed correctly in the console
console.log("id" + id);
console.log("newval" + newval);
and then I reload the Data-Table, but the value of id and newval is not correctly pass in the ajax, the value is send as null
If I change the initial value of id and newval as "a" and "b"
var id = "a";
var newval = "b";
then the value of id and newval passing through ajax is always "a" and "b", I need to pass the value that is displayed in the console in the ajax.
How Can I fix this?

To solve it, you need to pass a function to ajax.data:
"ajax": {
...
'data': function(d) {
d.TagId = id;
d.Values = newval;
},
...

Related

$(#id).html(content) function to set content to the next column

This is my HTML code:
<div class="row margin-top-3">
<div class="col-sm-7">
<h2>NFTs</h2>
<div class="table-responsive">
<table class="table table-bordered">
<thead>
<tr>
<th id = "NFTID">NFT ID</th>
<th id = "NFTNAME">NFT Name</th>
<th id = "NFTCREATOR">Creator</th>
</tr>
</thead>
<tbody id="NFT-rows">
</tbody>
</table>
</div>
</div>
</div>
The following three functions populate the table by column.
The problem is that the third function overwrites the second column instead of the third column.
Also, adding a fourth function will again overwrite the second column.
So, how can I re-write the $(#id).html(content) part to make it populate the next column instead of the second?
setupNFTRows: function() {
console.log("setupNFTrows NFT Array = " + JSON.stringify(NFTs));
console.log("NFT = " + Object.keys(NFTs))
Object.keys(NFTs).forEach(function (NFT) {
console.log("inside setupNFTrows");
$("#NFT-rows").append("<tr><td>" + "NFT_ID_" + NFT + "</td><td id='" + NFTs[NFT] + "'></td></tr>");
});
},
populateNFTNames: function() {
console.log("inside populateNFTNames")
let NFTIDs = Object.keys(NFTs);
console.log("NFTIDs = " + NFTIDs)
for(var i=0; i < NFTIDs.length; i++) {
let nftid = NFTIDs[i];
NFTContract.deployed().then(function(contractInstance) {
contractInstance.getNFTname.call(nftid).then(function(v) {
$("#" + NFTs[nftid]).html(v.toString());
})
})
}
},
populateCreators: function() {
let NFTIDs = Object.keys(NFTs);
for(var i=0; i < NFTIDs.length; i++) {
let nftid = NFTIDs[i];
NFTContract.deployed().then(function(contractInstance) {
contractInstance.getCreator.call(nftid).then(function(v) {
$("#" + NFTs[nftid]).html(v.toString());
})
})
}
},
This is because data tables are populated a row at a time, not a column at a time. The best way to approach this would be to zip your data together into a cohesive set to fill the rows:
const getNFTNames = (id) => {
NFTContract.deployed().then(contractInstance => {
contractInstance.getNFTname.call(nftid).then(v => {
return v.toString();
});
});
};
const getCreators = (id) => {
NFTContract.deployed().then(contractInstance => {
contractInstance.getCreator.call(nftid).then(v => {
return v.toString();
});
});
};
const setupNFTRows = () => {
Object.keys(NFTs).forEach(id => {
$("#NFT-rows").append(
`<tr id='NFT_ID_${id}'>
<td>NFT_ID_${id}</td>
<td>${getNFTNames(id)}</td>
<td>${getCreators(id)}</td>
</tr>`);
});
};

How to add minimum and maximum range filter with input field in datatable?

I have a table with multiple columns, each column has an input field to search through a particular column.
But for 4 columns, which are number-based, I wanted a range filter. That means, those 4 columns will have two input fields, the first is to put the minimum range number and the second is to put the maximum range number. Take a look at the reference image(it has only 2 columns out of 4 number-based columns, the other 2 are not visible in the screenshot).
Now I am trying to implement this functionality by adding my own search function to the datatable search function array, as given in the docs.
https://datatables.net/examples/plug-ins/range_filtering.html
But the search is not working, or i say it is not making any changes in UI at all.
this is the code -
// Call the dataTables jQuery plugin
$(document).ready(function() {
// Setup - add a text input to each footer cell
$('#dataTable thead tr').clone(true).appendTo('#dataTable thead');
$('#dataTable thead tr:eq(1) th').each( function (i) {
var title = $(this).text();
if(title==='clicks' || title==='impressions' || title==='ctr' || title==='position') {
$(this).html(`
<div class='d-flex'>
<input name=${title}_min id=${title}_min class='' type='number' min='0' placeholder='Min' style='width: 80px;'/>
<input name=${title}_max id=${title}_max class='ml-1' type='number' min='0' placeholder='Max' style='width: 80px;'/>
</div>
`);
var minInputValue = parseFloat($(`input[id=${title}_min]`, this).val()) || 0;
var maxInputValue = parseFloat($(`input[id=${title}_max]`, this).val()) || 0;
$.fn.dataTable.ext.search.push(function (settings, data, dataIndex) {
// logic to filter min and max values
var colVal = parseFloat(data[i]) || 0;
if (colVal >= minInputValue || colVal <= maxInputValue || minInputValue === 0 || maxInputValue === 0) {
return true;
}
return false;
});
$(`#${title}_min`, this).on('keyup change', function () {
minInputValue = parseFloat($(this).val()) || 0;
console.log('min', minInputValue);
dataTable.draw();
});
$(`#${title}_max`, this).on('keyup change', function () {
maxInputValue = parseFloat($(this).val()) || 0;
console.log('max', maxInputValue);
dataTable.draw();
});
} else {
$(this).html('<input type="text" placeholder="Search '+title+'" />');
$('input', this).on('keyup change', function () {
if (dataTable.column(i).search() !== this.value) {
dataTable.column(i).search(this.value).draw();
}
});
}
});
var dataTable = $('#dataTable').DataTable({
orderCellsTop: true,
paging: true,
scrollX: 400,
searching: true,
// lengthMenu: true,
dom: 'Blfrtip',
buttons: [
{ extend: 'csv', className: 'mb-2 btn btn-sm btn-info'},
{ extend: 'excel', className: 'mb-2 btn btn-sm btn-info' },
{ extend: 'pdf', className: 'mb-2 btn btn-sm btn-info' },
{ extend: 'print', className: 'mb-2 btn btn-sm btn-info' },
]
});
$('#dataTable_wrapper .dataTables_length').css({ display: 'inline-flex', 'margin-left': '20px' })
});
I really appreciate your help.
Your approach is close, but you need to expand the logic in your filter function:
$.fn.dataTable.ext.search.push(function (settings, data, dataIndex) {
// gather all the inputs we will need:
var clicks_val = parseFloat(data[2]) || 0.0;
var clicks_min = parseFloat($('#clicks_min').val()) || 0;
var clicks_max = parseFloat($('#clicks_max').val()) || Number.MAX_VALUE;
var impressions_val = parseFloat(data[3]) || 0.0;
var impressions_min = parseFloat($('#impressions_min').val()) || 0;
var impressions_max = parseFloat($('#impressions_max').val()) || Number.MAX_VALUE;
// evaluate to true to filter in a row, or false to filter it out:
var clicks = (clicks_val >= clicks_min && clicks_val <= clicks_max);
var impressions = (impressions_val >= impressions_min && impressions_val <= impressions_max);
// combine the above evaluations for overall row filtering:
return clicks && impressions;
});
Here I explicitly gather all the inputs needed to decide if a row should be visible or filtered out.
A demo:
$(document).ready(function() {
$.fn.dataTable.ext.search.push(function (settings, data, dataIndex) {
// gather all the inputs we will need:
var clicks_val = parseFloat(data[2]) || 0.0;
var clicks_min = parseFloat($('#clicks_min').val()) || 0;
var clicks_max = parseFloat($('#clicks_max').val()) || Number.MAX_VALUE;
var impressions_val = parseFloat(data[3]) || 0.0;
var impressions_min = parseFloat($('#impressions_min').val()) || 0;
var impressions_max = parseFloat($('#impressions_max').val()) || Number.MAX_VALUE;
// evaluate to true to filter in a row, or false to filter it out:
var clicks = (clicks_val >= clicks_min && clicks_val <= clicks_max);
var impressions = (impressions_val >= impressions_min && impressions_val <= impressions_max);
// combine the above evaluations for overall row filtering:
return clicks && impressions;
});
// Setup - add a text input to each footer cell
$('#dataTable thead tr').clone(true).appendTo('#dataTable thead');
$('#dataTable thead tr:eq(1) th').each( function (i) {
var title = $(this).text();
if(title==='clicks' || title==='impressions' ) {
$(this).html(`
<div class='d-flex'>
<input name=${title}_min id=${title}_min class='' type='number' min='0' placeholder='Min' style='width: 80px;'/>
<input name=${title}_max id=${title}_max class='ml-1' type='number' min='0' placeholder='Max' style='width: 80px;'/>
</div>
`);
$(`#${title}_min`, this).on('keyup change', function () {
minInputValue = parseFloat($(this).val()) || 0;
dataTable.draw();
});
$(`#${title}_max`, this).on('keyup change', function () {
maxInputValue = parseFloat($(this).val()) || 0;
dataTable.draw();
});
} else {
$(this).html('<input type="text" placeholder="Search '+title+'" />');
$('input', this).on('keyup change', function () {
if (dataTable.column(i).search() !== this.value) {
dataTable.column(i).search(this.value).draw();
}
});
}
});
var dataTable = $('#dataTable').DataTable({
orderCellsTop: true,
paging: true,
scrollX: 400,
searching: true,
// lengthMenu: true,
dom: 'Blfrtip',
buttons: [
{ extend: 'csv', className: 'mb-2 btn btn-sm btn-info'},
{ extend: 'excel', className: 'mb-2 btn btn-sm btn-info' },
{ extend: 'pdf', className: 'mb-2 btn btn-sm btn-info' },
{ extend: 'print', className: 'mb-2 btn btn-sm btn-info' },
]
});
$('#dataTable_wrapper .dataTables_length').css({ display: 'inline-flex', 'margin-left': '20px' })
});
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Demo</title>
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script src="https://cdn.datatables.net/1.10.22/js/jquery.dataTables.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.22/css/jquery.dataTables.css">
<link rel="stylesheet" type="text/css" href="https://datatables.net/media/css/site-examples.css">
</head>
<body>
<div style="margin: 20px;">
<table id="dataTable" class="display dataTable cell-border" style="width:100%">
<thead>
<tr>
<th>page</th>
<th>query</th>
<th>clicks</th>
<th>impressions</th>
</tr>
</thead>
<tbody>
<tr>
<td>https://google.comn</td>
<td>foo bar</td>
<td>1.2</td>
<td>3.4</td>
</tr>
<tr>
<td>https://google.comn</td>
<td>foo bar</td>
<td>2.3</td>
<td>4.5</td>
</tr>
<tr>
<td>https://google.comn</td>
<td>foo bar</td>
<td>3.4</td>
<td>5.6</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
Note also that we no longer need these:
var minInputValue = parseFloat($(`input[id=${title}_min]`, this).val()) || 0;
var maxInputValue = parseFloat($(`input[id=${title}_max]`, this).val()) || 0;
Update
Here is one approach to make your code more "generic" - by which I mean you do not have to explicitly capture separate variables for each cell value and each related min/max value:
$.fn.dataTable.ext.search.push(function ( settings, searchData, index, rowData, counter ) {
// assume the row is going to be displayed:
var result = true;
// loop through the cells we want to check:
$('#dataTable thead tr:eq(0) th').each( function (colIdx) {
var title = $(this).text();
if ( $(`#${title}_min`).length ) {
// gather all the inputs we will need to check one cell in the current row:
var val = parseFloat(searchData[colIdx]) || 0.0;
var min = parseFloat($(`#${title}_min`).val()) || 0;
var max = parseFloat($(`#${title}_max`).val()) || Number.MAX_VALUE;
//console.log( min, val, max ); // just for testing
if (val < min || val > max) {
result = false; // any one failure means the row is filtered out
}
}
} );
return result;
});
Only the $.fn.dataTable.ext.search.push function has changed, here. The rest of the code stays the same. I have tried to annotate the code to clarify what it is doing. I'm sure you could improve this even more, but this should give you some ideas.

using TableHTMLExport, how can i tell it to ignore certain divs and spans?

I am using
https://github.com/FuriosoJack/TableHTMLExport
I've got a rather complicated table with lots of hidden elements and I wanted a way to export this table using the said plugin. It works fine actually except it's also exporting all the hidden elements (style = display: hidden)
I've gone through the docs and I can't find the options for this.
All I could come up with is this:
$("#myTable").tableHTMLExport({
type: 'csv',
htmlContent: false,
filename: filename_csv,
ignoreColumns: '.export_ignore_col',
ignoreRows: '.export_ignore_row'
});
Alternative way :
You can read there documentation there is codepen link you can edit this code to achieve above . In below code i have made changes inside toCsv function .First i have check if the td or th has children and if the length > 0 then i have loop through childrens node and have check if they are visible or not depending on this i have appended value inside output variable.
Demo Code(with dummy datas) :
(function($) {
$.fn.extend({
tableHTMLExport: function(options) {
var defaults = {
separator: ',',
newline: '\r\n',
ignoreColumns: '',
ignoreRows: '',
type: 'csv',
htmlContent: false,
consoleLog: false,
trimContent: true,
quoteFields: true,
filename: 'tableHTMLExport.csv',
utf8BOM: true,
charSet: 'utf-8',
orientation: 'p' //only when exported to *pdf* "portrait" or "landscape" (or shortcuts "p" or "l")
};
var options = $.extend(defaults, options);
function quote(text) {
return '"' + text.replace('"', '""') + '"';
}
function parseString(data) {
if (defaults.htmlContent) {
content_data = data.html().trim();
} else {
content_data = data.text().trim();
}
return content_data;
}
function download(filename, text) {
var element = document.createElement('a');
element.setAttribute('href', 'data:text/csv;charset=' + options.charSet + ',' + encodeURIComponent(text));
element.setAttribute('download', filename);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
/**
* Convierte la tabla enviada a csv o texto
* #param table
* #returns {string}
*/
function toCsv(table) {
var output = "";
if (options.utf8BOM === true) {
output += '\ufeff';
}
var rows = table.find('tr').not(options.ignoreRows);
var numCols = rows.first().find("td,th").not(options.ignoreColumns).length;
rows.each(function() {
$(this).find("td,th").not(options.ignoreColumns)
.each(function(i, col) {
var column = $(col);
//check if td or th has children .ie. : any div or span..etc
if ($(col).children().length > 0) {
//loop through it
$(col).children().each(function() {
//check if the element is visible(not hidden)
if ($(this).is(':visible')) {
//append them inside output variable
output += $(this).text();
}
})
} else {
// Strip whitespaces
var content = options.trimContent ? $.trim(column.text()) : column.text();
output += options.quoteFields ? quote(content) : content;
}
if (i !== numCols - 1) {
output += options.separator;
} else {
output += options.newline;
}
});
});
console.log(" Output >>> " + output)
return output;
}
var el = this;
var dataMe;
if (options.type == 'csv' || options.type == 'txt') {
var table = this.filter('table'); // TODO use $.each
if (table.length <= 0) {
throw new Error('tableHTMLExport must be called on a <table> element')
}
if (table.length > 1) {
throw new Error('converting multiple table elements at once is not supported yet')
}
dataMe = toCsv(table);
if (defaults.consoleLog) {
console.log(dataMe);
}
download(options.filename, dataMe);
}
return this;
}
});
})(jQuery);
$("#tableCompany").tableHTMLExport({
type: 'csv',
filename: 'soemthingss.csv',
ignoreColumns: '.acciones,#primero',
ignoreRows: ''
});
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script src="https://unpkg.com/jspdf#1.5.3/dist/jspdf.min.js"></script>
<script src="https://unpkg.com/jspdf-autotable#3.2.3/dist/jspdf.plugin.autotable.js"></script>
<table id="tableCompany">
<thead>
<tr>
<th>Company</th>
<th>Contactt</th>
<th class='acciones'>Country</th>
</tr>
</thead>
<tbody>
<tr>
<td><span>Alfreds Futterkiste </span>
<div style="display:none">cdcdcdcdci</div>
<div>sti</div>
</td>
<td id="primero">Maria Anders</td>
<td class="acciones">Germany</td>
</tr>
<tr>
<td><span>Ernst Handel </span>
<div style="display:none">cdi</div>
<div>soemthinss</div>
</td>
<td>Roland Mendel</td>
<td class="acciones">Austria</td>
</tr>
<tr>
<td><span>Island Trading </span>
<div style="display:none">tr</div>
</td>
<td><span>Helen Bennett </span>
<div style="display:none">tr</div>
<div>twew</div>
</td>
<td>UK</td>
</tr>
</tbody>
</table>

jQuery create tables from JSON and group in expandable rows

I want to create a nested table with data from JSON file. here I use an array of object to simulate the back end:
var response = [
{
"mezzo":"fiat punto",
"tipologia":"auto",
"id":"1"
},
{
"mezzo":"fiat punto",
"tipologia":"auto",
"id":"2"
},
{
"mezzo":"fiat punto",
"tipologia":"auto",
"id":"3"
},
{
"mezzo":"alfa giulia",
"tipologia":"auto",
"id":"1"
},
{
"mezzo":"alfa giulia",
"tipologia":"auto",
"id":"2"
},
{
"mezzo":"fiat punto",
"tipologia":"auto",
"id":"4"
},
{
"mezzo":"alfa giulia",
"tipologia":"auto",
"id":"3"
}
];
I want to group my result table using the "mezzo" field, so I try sorting the array:
response.sort(function(a,b){
var mezzoA = a.mezzo.toLowerCase();
var mezzoB = b.mezzo.toLowerCase();
if (mezzoA > mezzoB) {
return -1;
}
if (mezzoA < mezzoB) {
return 1;
}
return 0;
});
now the jQuery code: I try to create elements and append to the DOM using .each() loop. the commented code works with hardcoded demo, but by now I have to group the rows matching the "mezzo" field in a single expandable row:
$(function () {
var parentFrag = document.createDocumentFragment();
$.each(response, function(i, item) {
var parentTr = document.createElement('tr');
var parentTd = '<td>></td><td>' + item.mezzo + '</td><td>' + item.tipologia + '</td><td>' + item.id +'</td>';
parentTr.innerHTML = parentTd;
parentFrag.appendChild(parentTr);
})
var parentTable = $('.parent');
parentTable[0].appendChild(parentFrag);
// Expand-Collapse details table
// $('table table').hide();
// $('td > a').on('click', function (e) {
// e.preventDefault();
// $(this).closest('tr').next().find('table:first').toggle();
// });
});
This is my html file:
<table border="1">
<thead>
<tr>
<td></td>
<td>Mezzo</td>
<td>Tipologia</td>
<td>ID</td>
</tr>
</thead>
<tbody class="parent">
</tbody>
</table>

DataTable with dropdown Column

I need to make dropdown as column in DataTable jQuery it is lookinng like as below right now
And I want it like the below image
and the code which I use is
<table id="example" class="hover row-border dataTable" role="grid" width="100%">
<thead class="dataTableHeader">
<tr>
<th>Days</th>
<th>Start Time</th>
<th>End Time</th>
</tr>
</thead>
</table>
$(document).ready(function () {
$('#example').DataTable({
"aaData": OrganizationData.OrganizationPreference.ScheduleDaysCol,
"columns": [
{"data": "DayName"},
{"data": "StartDateHour"},
{"data": "EndDateHour"}
],
"paging": false,
"ordering": false,
"info": false,
"filter": false
});
});
Another way would be to use the render method:
"render": function(d,t,r){
var $select = $("<select></select>", {
"id": r[0]+"start",
"value": d
});
$.each(times, function(k,v){
var $option = $("<option></option>", {
"text": v,
"value": v
});
if(d === v){
$option.attr("selected", "selected")
}
$select.append($option);
});
return $select.prop("outerHTML");
}
Working example.
You can use this way then for the dropdown setting
"aaData": OrganizationData.OrganizationPreference.ScheduleDaysCol,
"columnDefs": [{ "targets": 0,"data": "DayName" },
{
"targets": 1,
"data": "StartDateTime",
"render": function (data, type, full, meta) {
var $select = $("<select></select>", {
});
$.each(times, function (k, v) {
var $option = $("<option></option>", {
"text": v,
"value": v
});
if (data === v) {
$option.attr("selected", "selected")
}
$select.append($option);
});
return $select.prop("outerHTML");
}
DataTables seem to have an editor for this type of thing as refrenced by Samyukta and others: https://editor.datatables.net/examples/inline-editing/simple
I would say that is the easiest answer. It is however, a commercial extension with a free trial only.
If you wanted some jquery code to simply change the static times to dropdown boxes, you could give this a shot:
//utility functions to get half-hour increment lists
function getTimeList(){
var iterations = 48;
var result = [];
for(int i = 0; i < iterations; i++){
var hour = Math.floor(i / 2);
var minute = (i % 2) > 0 ? '30' : '00';
result.push(hour + ':' + minute);
}
return result;
}
function getOptionTimeList(){
var raw = getTimeList();
var iterations = raw.length;
var result = '';
for(int i = 0; i < iterations; i++){
result = result + '<option>' + raw[i] + '</option>';
}
return result;
}
//I'm using the not selector to avoid changing the days into dropdown by accident
$('#example tbody tr td:not(#example tbody tr:first-child)').each(
function(index, element){
var value = element.innerHTML;
var optionList = getOptionTimeList();
var replacement = '<td><select>' + optionList + '</select></td>';
$(element).replaceWith(replacement)
}
);
This should get you the drop down boxes where you need them. I'll revise this if you have problems with it.
You can try to use this, this is what i'm using now.
https://github.com/ejbeaty/CellEdit
Look at this example:
"inputTypes": [
{
"column":0,
"type":"text",
"options":null
},
{
"column":1,
"type": "list",
"options":[
{ "value": "1", "display": "Beaty" },
{ "value": "2", "display": "Doe" },
{ "value": "3", "display": "Dirt" }
]
}
Hope it help someone.

Categories

Resources