DataTable with dropdown Column - javascript

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.

Related

Parameter Not Passing in jquery dataTable Ajax Call

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;
},
...

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>

Reducing code with the use of Handlebars.js

I'm beginning to use Handlebars and the architectural pattern Model View ViewModel and I wrote this code :
var data = {
currentPlayer: this._model.currentPlayer,
line: [
{
row:
[
{
caseNumber:1,
caseValue: this._model.getCaseState(0,0)
},
{
caseNumber:2,
caseValue: this._model.getCaseState(0,1)
},
{
caseNumber:3,
caseValue: this._model.getCaseState(0,2)
}
]
},
{
row:[
{
caseNumber:4,
caseValue:this._model.getCaseState(1,0)
},
{
caseNumber:5,
caseValue:this._model.getCaseState(1,1)
},
{
caseNumber:6,
caseValue:this._model.getCaseState(1,2)
}
]
},
{
row:[
{
caseNumber:7,
caseValue:this._model.getCaseState(2,0)
},
{
caseNumber:8,
caseValue:this._model.getCaseState(2,1)
},
{
caseNumber:9,
caseValue: this._model.getCaseState(2,2)
}
]
}
]
};
var htmlContent = this._template(data);
this._element.html(htmlContent);
With the following template :
<div>
<h3>It is to player {{currentPlayer}}</h3>
<table>
{{#each line}}
<tr>
{{#row}}
<td data="{{caseNumber}}" class="case{{caseValue}}">{{caseValue}}</td>
{{/row}}
</tr>
{{/each}}
</table>
</div>
This code works fine but I'm asking if I cannot reduce it. So I tried to use a for loop in the var data but I realized that I can't do this.
My other choice was to use an if in the template like this :
{{#each line}}
<tr>
{{#row}}
{{#if caseValue}}
<td data="{{caseNumber}}" class="case{{caseValue}}">O</td>
{{else}}
<td data="{{caseNumber}}" class="case{{caseValue}}">X</td>
{{/if}}
{{/row}}
</tr>
{{/each}}
by testing the value of the var caseValue. However, as caseValue takes the value of 1 or 0 or undefined, if the case isn't checked all the cells are filled with a "X".
So, I can't find a compact solution with the aim of :
At the beginning, all the TD tags are empty.
Depending on the value of getCaseState which returns 0 or 1 fill
the cell with an "X" or an "O".
EDIT : I manage the different values of getCaseState with this code :
Handlebars.registerHelper('displayTd', function(data) {
var result;
if(data.caseValue === undefined) {
result = '<td data="' + data.caseNumber + '"></td>';
return new Handlebars.SafeString(result);
} else if(data.caseValue === 1) {
result = '<td data="' + data.caseNumber + '" class="case' + data.caseValue + '">X</td>';
return new Handlebars.SafeString(result);
} else {
result = '<td data="' + data.caseNumber + '" class="case' + data.caseValue + '">O</td>';
return new Handlebars.SafeString(result);
}
});
The first step I would take to reduce the code was the one you alluded to about using loops to construct your data. The data in your line object follows a simple pattern, so we can construct with the following code:
var numRows = 3;
var numColumns = 3;
var line = [];
for (var rowIndex = 0; rowIndex < numRows; rowIndex++) {
line[rowIndex] = { row: [] };
for (var columnIndex = 0; columnIndex < numColumns; columnIndex++) {
line[rowIndex].row[columnIndex] = {
caseNumber: ((rowIndex * numColumns) + columnIndex + 1),
caseValue: getCaseState(rowIndex, columnIndex)
};
}
}
*Note that you will have to call getCaseState on your existing model object.
Our data object then becomes:
var data = {
currentPlayer: this._model.currentPlayer,
line: line
};
As for the conditional within your template, I would recommend creating your own Handlebars helper. Fortunately, Handlebars has an isEmpty utility method that returns true for:
Array with length 0
falsy values other than 0
This means that we can use this utility method to check if our caseValue is undefined:
Handlebars.registerHelper('getCharacter', function (caseValue) {
return Handlebars.Utils.isEmpty(caseValue) ? '' : (caseValue === 0 ? 'X' : 'O');
});
We then use our new helper in our template in the following way:
{{#each row}}
<td data="{{caseNumber}}" class="case{{caseValue}}">{{getCharacter caseValue}}</td>
{{/each}}

How to populate Javascript table with JSON array?

I have JSON array similar to this :
{"X":[
{"Time":"05:45","Count":70},
{"Time":"06:30","Count":40},
{"Time":"08:15","Count":80}
]},
{"Y":[
{"Time":"09:15","Count":70},
{"Time":"10:30","Count":84},
{"Time":"12:00","Count":95}
]},
{"Z":[
{"Time":"14:00","Count":80},
{"Time":"16:00","Count":70},
{"Time":"15:00","Count":40}
]}
I have to populate table like this dynamically :
Name 05:45 06:30 08:15 09:15 10:30 12:00 14:00 16:00 15:00
X 70 40 80 0 0 0 0 0 0
Y 0 0 0 70 84 95 0 0 0
Z 0 0 0 0 0 0 80 70 40
I don't know how to populate this as Javascript table. Could anyone please help me with this?
Use JSON.parse(//your json string).
Now you can dynamically create rows by looping through this json array something like this--
var DataArray = JSON.parse(data.d);
var tableelement = $("#DataSetTbl"); //get table id from jquery
tableelement.append(createRow(DataArray)); //call this function from the action you want to show table
function createRow(Object) { //dynamically adding rows to the Table
var trElement = "<tr>"; //design this according to your requirement
for(var s=0;s<Object.length; s++)
trElement += "<td >" + Object[s].Time + "</td>";
return trElement;
}
Similarly append a new row for count :)
var data = {
"X":[
{"Time":"05:45","Count":70},
{"Time":"06:30","Count":40},
{"Time":"08:15","Count":80}
],
"Y":[
{"Time":"09:15","Count":70},
{"Time":"10:30","Count":84},
{"Time":"12:00","Count":95}
],
"Z":[
{"Time":"14:00","Count":80},
{"Time":"16:00","Count":70},
{"Time":"15:00","Count":40}
]
};
var keys = Object.keys(data), times = {}, rows = {};
(function processData(){
var row, key, r;
for(key in data) {
row = rows[key] = {};
for(r in data[key]) addInfo(row, data[key][r]);
}
function addInfo(row, record) {
times[record.Time] = true;
row[record.Time] = record.Count;
}
})();
(function createTable() {
var key,
count,
time,
tr = $('<tr>'),
$body = $('body'),
$table = $('<table>'),
$thead = $('<thead>'),
$tbody = $('<tbody>');
$body.append($table);
$table.append($thead);
$table.append($tbody);
$thead.append(tr);
tr.append('<th>name</th>');
for(time in times) tr.append('<th>'+time+'</th>');
for(key in rows) {
tr = $('<tr>');
tr.append('<th>'+key+'</th>');
for(time in times) {
count = (rows[key][time] || 0);
tr.append('<td>'+count+'</td>');
}
$tbody.append(tr);
}
})();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
You would have to correct your data so it is a proper object as show in the demo below.
First so that you may be able to iterate through the times combine all the array data into array, say a
Iterate through the keys of the object and the iterate through the elements of a
If current element of a exists in the value of the outer iteration, val, then output elm.Count, otherwise output 0.
var o = {
"X":[
{"Time":"05:45","Count":70},
{"Time":"06:30","Count":40},
{"Time":"08:15","Count":80}
],
"Y":[
{"Time":"09:15","Count":70},
{"Time":"10:30","Count":84},
{"Time":"12:00","Count":95}
],
"Z":[
{"Time":"14:00","Count":80},
{"Time":"16:00","Count":70},
{"Time":"15:00","Count":40}
]
};
//merge arrays for purpose getting all times
var a = [];
$.each(o, function(k,v) {
a = a.concat( v );
});
//select table
var table = $('table');
//create row to clone
var row = $('<tr/>');
//construct header
var theadRow = row.clone().html( '<th>Name</th>' );
$.each(a, function(i,v) {
theadRow.append( '<th>' + v.Time + '</th>' );
});
//append header row to table
table.find('thead').append( theadRow );
//rows
var tbody = table.find('tbody');
$.each(o, function(key,val) {
//construct row
var tbodyRow = row.clone().html( '<th>' + key + '</th>' );
$.each(a, function(index, elm) {
tbodyRow.append( '<td>' + (val.indexOf( elm ) > -1 ? elm.Count : 0) + '</td>' );
});
//append row to table
tbody.append( tbodyRow );
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<thead></thead>
<tbody></tbody>
</table>
Try creating valid json array of objects , utilizing $.each() , .after() , Object.keys() ; table , tr, tbody , tr , td elements ; css
$(function() {
var data = [{
"X": [{
"Time": "05:45",
"Count": 70
}, {
"Time": "06:30",
"Count": 40
}, {
"Time": "08:15",
"Count": 80
}]
}, {
"Y": [{
"Time": "09:15",
"Count": 70
}, {
"Time": "10:30",
"Count": 84
}, {
"Time": "12:00",
"Count": 95
}]
}, {
"Z": [{
"Time": "14:00",
"Count": 80
}, {
"Time": "15:00",
"Count": 70
}, {
"Time": "16:00",
"Count": 40
}]
}];
res = {};
var table = $("<table><tbody></tbody></table>");
$.each(data, function(key, value) {
var name = Object.keys(value)[0];
table.find("tbody")
.append("<tr class=" + name + "><td>" + name + "</td></tr>");
if (!res[name]) {
res[name] = [];
}
$.each(value[name], function(index, obj) {
res[name].push([obj.Count, obj.Time])
table.append("<th>" + obj.Time + "</th>");
return obj.Time
});
table.find("th").prependTo(table)
});
table.find("th:first").before("<th>Name</th>");
$.each(res, function(index, count) {
$("tr[class=" + index + "]", table).after(function() {
return $.map(Array($("th", table).length - 1), function(v, k) {
var html = count.filter(function(val) {
return val[1] === $("th", table).eq(k + 1).text()
});
return "<tr><td>" + (!!html.length ? html[0][0] : 0) + "</td></tr>"
})
})
});
table.appendTo("body")
});
table tr:not([class]),
table th {
display: inline-block;
}
table tr:not([class]) {
width: 39px;
position: relative;
left: 44px;
top:-24px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>

Find element by data attributes that use "|" as separators

Fiddle Example
HTML markup:
<div data-id='23|24|25'></div>
<div data-id='29|30|31'></div>
Script:
var array = [
{
"mid": "24"
},
{
"mid": "26"
},
{
"mid": "28"
},
{
"mid": "29"
},
{
"mid": "30"
},
{
"mid": "31"
}
];
var item_html ="";
$.each(array,function(i,k) {
item_html = '<h3>'+k["mid"]+'</h3>';
$('div[data-id="'+k["mid"]+'"').append(item_html); ???????????
});
Would it be possible to find the div element if part of the "|" separated value in its data-id matches the mid?
I'm trying to get an output like this:
<div data-id='23|24|25'>
<h3>24</h3>
</div>
<div data-id='29|30|31'>
<h3>29</h3>
<h3>30</h3>
<h3>31</h3>
You should use the *= selector (contains):
$('div[data-id*="'+k["mid"]+'"').append(item_html);
The result you are looking for is something tricky. I have update your code. hope this will help you.
var array = [
{ "mid": "24"},
{"mid": "26"},
{"mid": "28"},
{"mid": "29"},
{"mid": "30"},
{"mid": "31"}
];
$('[data-id]').each(function(){
var $this = $(this), dataArr = $this.data('id').split('|'), i = 0;
for(;i< dataArr.length; i++) {
if(numInObjArr(array,dataArr[i])) {
$this.append('<h3>'+ dataArr[i] +'</h3>');
}
}
});
//function to check number in array object provided above
function numInObjArr(objArr, num){
for (var i = 0, len=objArr.length; i< len; i++){
if(objArr[i]["mid"] == num) {
return true;
}
}
return false;
}
http://jsfiddle.net/EZ56N/73/ to see the working example

Categories

Resources