How to loop inside datatable columns declaration? - javascript

I have the below datatable declaration and want to display images depend on some column value (team_members). How can I declare the for loop inside columns declaration? i want this result:
var datatableVariable = $('#projects-progress').DataTable({
data: data,
columns: [
{ 'data': 'project_name' },
{ 'data': 'team_members_value' }, // to be hidden
{
//I want loop here depend on the number of team_members_value (second column above)
mRender: function (o) { return '<img src="images/img.jpg" class="avatar" alt="Avatar">';
},
/* EDIT Delete */
{
mRender: function (o) { return '<i class="fa fa-folder"></i> View <i class="fa fa-pencil"></i> Edit <i class="fa fa-trash-o"></i> Delete '; }
},
]
});
<table id="projects-progress" class="table table-striped projects">
<thead>
<tr>
<th>Project Name</th>
<th>Team Members</th>
<th>Actions</th>
</tr>
</thead>
</table>

You can use parameter render in column declaration.
{
"data": "team_members_value",
"render": function (data, type, full, meta) {
var markup = '';
for (var i = 0; i < data; i++) {
markup +='<img src="images/img.jpg" class="avatar" alt="Avatar">'
});
return markup ;
}
}
You need to do something like this:
Add render callback.
Proceed your team_members_value data to render needed markup, save it and return.

Related

DataTable - Appending Additional column is throwing some Exception Error

I'm trying to implement Server Side DataTable.
Everything goes perfectly fine up to the last rowCallback where I'm appending button to additional column for Actions (i.e. Edit/Delete).
Issue:
Here's my code.
<link href="~/Content/datatables.min.css" rel="stylesheet" /> //<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/dt-1.10.16/datatables.min.css"/>
<link href="~/Content/font-awesome.min.css" rel="stylesheet" />
<div class="container">
<div class="row" style="margin-top:25px">
<table class="table table-bordered table-responsive dataTables-list">
<thead>
<tr>
<th>
Id
</th>
<th>
Name
</th>
<th>
Actions
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Id)
</td>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
<i class="fa fa-pencil"></i>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
JavaScript:
<script src="~/Scripts/datatables.min.js"></script> //<script type="text/javascript" src="https://cdn.datatables.net/v/dt/dt-1.10.16/datatables.min.js"></script>
<script>
$(document).ready(function () {
$('.dataTables-list').DataTable({
/*Sorting*/
"bSort": true,
"aoColumnDefs": [{
'bSortable': true
}],
"processing": true, // for show progress bar
"serverSide": true, // for process server side
"ajax": {
"url": "/Home/LoadData",
"type": "POST",
"datatype": "json"
},
"aoColumns": [{
"mDataProp": "Id"
}, {
"mDataProp": "Name"
}, {
"mDataProp": "Actions"
}],
"rowCallback": function (row, data, index) {
var newBtns = '<i class="fa fa-pencil"></i> ';
// $(row).append(newBtns);
$('td:eq(2)', row).html(newBtns);
},
language: {
paginate: {
next: '»',
previous: '«'
},
emptyTable: "Der er ingen poster.",
sInfo: "Viser _START_ til _END_ af poster."
}
});
});
</script>
Controller:
[HttpPost]
public ActionResult LoadData()
{
try
{
var draw = Request.Form.GetValues("draw").FirstOrDefault();
var start = Request.Form.GetValues("start").FirstOrDefault();
var length = Request.Form.GetValues("length").FirstOrDefault();
//Find Order Column
var sortColumn = Request.Form.GetValues("columns[" + Request.Form.GetValues("order[0][column]").FirstOrDefault() + "][data]").FirstOrDefault();
var sortColumnDir = Request.Form.GetValues("order[0][dir]").FirstOrDefault();
int pageSize = length != null ? Convert.ToInt32(length) : 0;
int skip = start != null ? Convert.ToInt32(start) : 0;
int recordsTotal = 0;
var v = (from a in _db.AllRoles select a); //Table contains only two Columns - Id and Name
//SORT
if (!(string.IsNullOrEmpty(sortColumn) && string.IsNullOrEmpty(sortColumnDir)))
{
v = v.OrderBy(sortColumn + " " + sortColumnDir);
}
recordsTotal = v.Count();
var data = v.Skip(skip).Take(pageSize).ToList();
return Json(new { draw = draw, recordsFiltered = recordsTotal, recordsTotal = recordsTotal, data = data }, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
throw;
}
}
The issue is due to column difference may be but I don't know how to solve it as implementing ServerSide Datatable for first time.
Thanks in advance.
I modified the below section in my Code to solve the Error.
"aoColumns": [{
"mDataProp": "Id"
}, {
"mDataProp": "Name"
}, {
"mDataProp": "Actions",
"defaultContent": '<i class="fa fa-pencil"></i> '
}],
I added defaultContent for that column as it is not getting values from Database/Sp.
P.S. Answer provided by #dee is also correct and will solve the error. Both are the Solutions to this Question.
The link in the error message provides very good information about what is the problem. You have specified three columns for the DataTable function but as you write in the comment Table contains only two Columns - Id and Name.
"aoColumns": [{
"mDataProp": "Id"
}, {
"mDataProp": "Name"
}, {
"mDataProp": "Actions"
}],
The Resolution section of the document tells what is needed to do:
If using columns ensure that you have specified exactly the number of columns that are present in the HTML for the table.
So you will need the transform the result of the query into another class which will have additional property for Actions. HTH

Hyperlink gets disabled when reinitializing JQuery DataTable

The following code samples demonstrates how I initialize a jQuery Datatable with HTML, knockout and typescript
HTML:
<table id="coursemoment-info-table" class="table table-hover">
<thead>
<tr >
// headers
</tr>
</thead>
<tbody>
<!-- ko foreach: selectedCourseMoment().courseApplications -->
<tr>
<td>
<a data-bind="{text: ssn, attr:{ href: '/Medlem/' + ssn} }"></a>
</td>
<td data-bind="text:name + ' ' + surname"></td>
.
.
.
</tr>
<!-- /ko-->
</tbody>
</table>
Typescript:
private initCourseMomentInformationDataTable(): void {
$("#coursemoment-info-table").DataTable({
pageLength: 5,
order: [1, 'desc'],
language: {
url: "/Assets/js/jquery-datatable-swedish.json"
}
});
}
I have had some problems with reinitializing the table, but I managed to handle it with first clearing the datatable, and then adding rows to the datatable and redraw it.
if (this.tableInitiliazed) {
$("#coursemoment-info-table").DataTable().clear().draw();
for (var i = 0; i < data.courseApplications.length; i++) {
var application = data.courseApplications[i];
$("#coursemoment-info-table").DataTable().row.add(
[
application.ssn,
// blah blah yada yada
]).draw();
}
This does indeed reinitiliaze the datatable, but it does not put a hyperlink to the first column as it does when initializing the table. All the other table settings are correct, such as language and pagelength.
Since I add one row at a time, with the multiple columns I do not know how to set column settings for "applications.ssn" directly. I have tried to initialize the datatable in the viewmodel with typescript but I get the same problem.
Any ideas how to reinitialize and put a hyperlink setting for a specific column?
I think you want to use Datatables render to create your link. so here is a custom data binder for data table that uses render to create the link.
here is the fiddle to see it in action. http://jsfiddle.net/LkqTU/35823/
ko.bindingHandlers.dataTable = {
init: function(element, valueAccessor, allBindingsAccessor) {
var value = valueAccessor(),
rows = ko.toJS(value);
allBindings = ko.utils.unwrapObservable(allBindingsAccessor()),
$element = $(element);
var table = $element.DataTable( {
data: rows,
columns: [
{ data: "id" },
{ data: "firstName" },
{ data: "lastName" },
{ data: "phone" },
{
data: "ssn",
"render": function ( data, type, full, meta ) {
return '<a href="/Medlem/'+data+'">' + data + '<a>';
}
}
]
} );
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
$element.dataTable().fnDestroy();
});
value.subscribe(function(newValue) {
rows = ko.toJS(newValue)
console.log(rows);
$element.find("tbody tr").remove();
table.rows().remove().draw();
setTimeout(function(){ $.each(rows, function( index, row ) {
table.row.add(row).draw()
});
}, 0);
}, null);
}
}

jquery data table action button

Can anyone help me about the best approach to add action button like edit, delete in each row in jquery data table?
I had gone through some links but didn't find a solution.
$(document).ready(function () {
$.ajax({
url: '#Url.Action("GetStudentGridData", "UserManagement")',
type: "GET",
dataType: 'json',
success: function (data) {
$('#student-datatable').DataTable({
data: data,
aoColumns: [
{ mData: "FirstName" },
{ mData: "Class" },
{ mData: "Roll" },
{ mData: "PresentAddress" },
{ mData: "BloodGroup" },
{ mData: "RegisterDate" },
{
mRender: function (data, type, full) {
return 'Edit';
}
}
]
});
},
error: function () {
alert("An error has occured!!!");
}
});
});
Here is the js code that I used to render data table. Each row has a student details and in my return 'data' object I had studentID property. I want to fetch data using that studentID when user click Edit button in a row.
Kindly help me about how to render edit and delete button and also how to handle them.
Solution :
I have tried a new approach. Instead of rendering column using datatable property I have added button in html
<table id="student-datatable" class="table table-striped table-bordered table-hover table-highlight table-checkable" cellspacing="0">
<thead>
<tr>
<th>Name</th>
<th>Class</th>
<th>Roll</th>
<th>PresentAddress</th>
<th>Blood Group</th>
<th>Register Date</th>
<th>Action</th>
</tr>
</thead>
<tbody>
#{
foreach (var cl in Model)
{
<tr>
<td>#cl.FirstName #cl.LastName</td>
<td>#cl.Class</td>
<td>#cl.Roll</td>
<td>#cl.PresentAddress</td>
<td>#cl.BloodGroup</td>
<td>#cl.RegisterDate</td>
<td>
<div >
<button type="button" class="btn btn-default edit-student-btn" data-student-id="#cl.StudentID"><i class="fa fa-edit"></i></button>
<button type="button" class="btn btn-default"><i class="fa fa-trash"></i></button>
</div>
</td>
</tr>
}
}
</tbody>
Then I just call the jquery datatable method.
$(document).ready(function () {
$('#student-datatable').DataTable();
});
This give me nice output:
In this case, you have to use event delegation for elements added dynamically.
Event delegation allows us to attach a single event listener, to a
parent element, that will fire for all descendants matching a
selector, whether those descendants exist now or are added in the
future.
You should bind click event handler using .on() method.
$(document).on('click','.editUser',function(){
var studentID=$(this).closest('tr').find('td').eq(6).html();
});

How to hide particular data to expose in server side datatable processing

Currently I am doing datatable server side ajax processing. Scenario is:
As like normal datatable operations i.e. sorting-searching-pagination.
one Column(say the last one) with action header will contain the action buttons like ADD/EDIT/DELETE/MARK/CACHE etc.
Based on user role and its access permission user can access particular buttons which is assigned by admin. For Example,
User with Role=1 has ADD-EDIT button enabled.
User with Role=2 has EDIT-DELETEbutton enabled
When userrole 1 or 2 is logged in user can see and access only that buttons.
If I pass the access information from JSP's(getting info from session object) script tag to main javascript function and with If-Else condition it can be done.BUT the access information is exposed to client.
REQUIREMENT: I want to create buttons dynamically but in server side(Java-Spring) or hiding the logic from user.
so far this is my try:
script.js
function getDatatable(id, url, columns) {
globalDatatable = $('#' + id).DataTable({
lengthChange : false,
processing : true,
serverSide : true,
order : [ [ 0, 'asc' ] ],
paging : true,
fnDrawCallback : function(oSettings) {
},
ajax : {
url : url,
type : "GET",
datatype : "application/json",
data : function(d) {
return JSON.stringify(d);
}
},
initComplete : function(settings, json) {
},
columns : columns,
});
}
function getIpRangeDatatable(id,url){
var columns=[];
columns.push({ data: "ipid" ,name:"ipid"});
columns.push({ data: "startIp",name:"startIp" });
columns.push({ data: "endIp",name:"endIp" });
columns.push({ data: "allow",name:"allow" });
columns.push({ data: "roleName" ,name:"roleName"});
columns.push({ data: "description" ,name:"description"});
columns.push({ data: "loginId",name:"loginId" });
columns.push({ data:function(o1){ return parseDateTime(o1.fromDate); },name:"fromDate" });
columns.push({ data: function(o1){ return parseDateTime(o1.toDate); },name:"toDate" });
columns.push({ data: function(o1){
var buttons=[{name:"Edit", action:"doOperations(2,12,3,"+o1.ipid+")"}
,{name:"Delete", action:"doOperations(3,12,4,"+o1.ipid+")"}];
return getActionMenus(buttons);
}});
getDatatable(id,url,columns);
}
function getActionMenus(buttons) {
var menu= "<div class='btn-group'>"+
"<button type='button' class='btn btn-default'><span class='glyphicon glyphicon-share' aria-hidden='true'></span> Action</button>"+
"<button type='button' class='btn btn-default dropdown-toggle' data-toggle='dropdown' aria-haspopup='true' aria-expanded='false'> <span class='caret'></span> <span class='sr-only'>Toggle Dropdown</span> </button>"+
"<ul class='dropdown-menu dropdown-menu-right'>";
for(var i in buttons ){
menu+="<li><a href='javascript:"+buttons[i].action+"' data-title='IpRange'><span class='glyphicon glyphicon-edit' aria-hidden='true'></span>"+ buttons[i].name+"</a></li>";
}
menu+="</ul></div>";
return menu;
}
Test.jsp
<%
String ctxPath = request.getContextPath() + "/";
String id = "ipRange_" + Utils.getUUID();
%>
<div class="wrapper-content-area-pad">
<div class="panel panel-primary flat-panel">
<div class="panel-heading flat-panel">IP Range Details</div>
<div class="panel-body">
<a href="javascript:doGenericOperations(2,12,3,0)"class="btn btn-default" data-title="IpRange">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>Add IP</a>
<table id="<%=id%>"
class="table compact table-striped table-bordered table-action" cellspacing="0"
width="100%">
<thead>
<tr>
<th>IPId</th>
<th>Start IP</th>
<th>End IP</th>
<th>Allow Rule</th>
<th>Type of User</th>
<th>Description</th>
<th>Username</th>
<th>From Date</th>
<th>To Date</th>
<th>Actions</th>
</tr>
</thead>
</table>
</div>
</div>
</div>
<script>
$(document).ready(function(){
getIpRangeDatatable('<%=id%>', 'appAdmin/s/manage_ip/datatable/1');
});
</script>
JSON data sample:
{"draw":1,"recordsFiltered":6,"data":[{"ipid":11,"startIp":"172.16.0.0","endIp":"172.16.255.255","allow":0,"allowNull":false,"description":"Faculty ip range ","roomId":0,"roomIdNull":false,"fromDate":null,"toDate":1474889095000,"userId":9295,"userIdNull":false,"roleName":"Faculty","userRoleId":4,"userRoleIdNull":false,"loginId":"shylaja.sharath#pes.edu"},{"ipid":12,"startIp":"10.10.101.10","endIp":"10.10.101.10","allow":0,"allowNull":false,"description":"Tech team Ubuntu","roomId":0,"roomIdNull":false,"fromDate":null,"toDate":null,"userId":0,"userIdNull":true,"roleName":"Student","userRoleId":3,"userRoleIdNull":false,"loginId":null},{"ipid":13,"startIp":"172.16.0.1000","endIp":"172.16.255.255","allow":0,"allowNull":false,"description":"Faculty ip range ","roomId":0,"roomIdNull":false,"fromDate":null,"toDate":null,"userId":0,"userIdNull":true,"roleName":null,"userRoleId":0,"userRoleIdNull":true,"loginId":null},{"ipid":18,"startIp":"172.16.174.40","endIp":"172.16.174.40","allow":1,"allowNull":false,"description":"Faculty IP Range","roomId":12,"roomIdNull":false,"fromDate":null,"toDate":null,"userId":0,"userIdNull":true,"roleName":"Faculty","userRoleId":4,"userRoleIdNull":false,"loginId":null},{"ipid":20,"startIp":"192.168.1.12","endIp":"192.168.3.35","allow":0,"allowNull":false,"description":"","roomId":0,"roomIdNull":false,"fromDate":null,"toDate":null,"userId":0,"userIdNull":true,"roleName":null,"userRoleId":0,"userRoleIdNull":true,"loginId":null},{"ipid":21,"startIp":"1.1.1.1","endIp":"192.168.1.255","allow":0,"allowNull":false,"description":"","roomId":0,"roomIdNull":true,"fromDate":null,"toDate":null,"userId":0,"userIdNull":true,"roleName":null,"userRoleId":0,"userRoleIdNull":true,"loginId":null}],"recordsTotal":6}

Displaying image on Datatable

I am using server side processing to read the database table and convert the records into Json file, and pass it to the database table to display data.
Read database and convert it into json:
code:
Route::get('banner/list/banners/json/{id}', function ()
{
$banner = DB::table('banner_creatives')->where('Id','=','53')->get();
$recordsTotal = count($banner);
$data['draw'] = 1;
$data['recordsTotal'] = $recordsTotal;
$data['recordsFiltered'] = $recordsTotal;
$data['data'] = $banner;
return Response::json($data);
});
Json output:
{"draw":1,"recordsTotal":1,"recordsFiltered":1,"data":[{"id":1,"bId":26,"cId":53,"bName":"32_32_53.jpeg","storageType":"url","width":32,"height":32,"weight":1,"imageURL":"localhost:8000\\\/banner\\\/view\\\/32_32_53.jpeg","clickURL":"","created_at":"2015-01-26 12:32:28","updated_at":"2015-01-26 12:32:28","deleted_at":null}]}
As you can see on this json, I have the image Url that I want to display it on the table.
JavaScript code:
$(document).ready(function() {
var table = $('#banner').DataTable( {
"processing": true,
"serverSide": false,
"ajax": "banners/json/53",
"columns": [
{ "data": "id" },
{ "data": "bannerId" },
{ "data": "campaignId" },
{ "data": "bannerName" },
{ "data": "width" },
{ "data": "height" },
{ "data": "imageUrl" }
});
});
Datatable code:
<table id="banner" class="display table table-striped table-bordered table-hover dataTable no-footer" cellspacing="0" width="100%">
<thead>
<tr>
<th>id</th>
<th>Banner Id</th>
<th>Campaign Id</th>
<th>Banner Name</th>
<th>Width</th>
<th>Height</th>
<th>Image/Banner</th>
</tr>
</thead>
<tfoot>
<tr>
<th>id</th>
<th>Banner Id</th>
<th>Campaign Id</th>
<th>Banner Name</th>
<th>Width</th>
<th>Height</th>
<th>Image/Banner</th>
</tr>
</tfoot>
</table>
On the last column it displaying the image URL but is not what i want, i want to display the usually image on the datatable using the URL, if it possible.
You can use the columns.render option to specify a callback function that can modify the data that is rendered in the column.
The callback function takes three parameters (four since 1.10.1). The first parameter is the original data for the cell (the data from the db), the second parameter is the call type (filter, display, type, or sort), and the third parameter is the full data source for the row. The function should return the string that should be rendered in the cell.
In your columns definition, add the render option to your imageUrl column definition:
{
"data": "imageUrl",
"render": function(data, type, row) {
return '<img src="'+data+'" />';
}
}
Documentation on the render option found here.
Here's my solution, hope it helps someone.
{
'targets': [15,16],
'searchable': false,
'orderable':false,
'render': function (data, type, full, meta) {
return '<img src="'+data+'" style="height:100px;width:100px;"/>';
}
},
"columnDefs": [
{
// The `data` parameter refers to the data for the cell (defined by the
// `data` option, which defaults to the column being worked with, in
// this case `data: 0`.
"render": function ( data, type, row ) {
return '<img src="'+data+'" style="width=300px;height=300px;" />';
},
"targets": 1 // column index
}
]

Categories