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

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}

Related

Laravel - DataTables warning: table id=userTable - Invalid JSON response (This request has no response data available)

I am trying to retrieve data from database and display it into Data Table but this error is keep appearing:
DataTables warning: table id=userTable - Invalid JSON response. For more information about this error, please see http://datatables.net/tn/1
When I tried to check its response in Developer tools (I use Chromium Edge) it does not have any data and contains only message:
This request has no response data available
I have this in my web.php:
Route::get('user/datatable', 'UserController#datatable')->name('user/datatable')->middleware('role:admin');
My snippet code from controller file (UserController):
public function datatable()
{
$data = User::where('status', '=', 1)->get();
return DataTables::of($data)
->addColumn('action', function($data){
$url_edit = url('user/'.$data->id.'/edit');
$url = url('user/'.$data->id);
$view = "<a class = 'btn btn-primary' href = '".$url."' title = 'View'><i class = 'nav icon fas fa-eye'></i></a>";
$edit = "<a class = 'btn btn-warning' href = '".$url_edit."' title = 'Edit'><i class = 'nav icon fas fa-edit'></i></a>";
$delete = "<button data-url = '".$url."' onclick = 'deleteData(this)' class = 'btn btn-action btn-danger' title = 'Delete'><i class = 'nav-icon fas fa-trash-alt'></i></button>";
return $view."".$edit."".$delete;
})
->rawColumns(['action'])
->editColumn('id', 'ID:{{$user_id}}')
->make(true);
}
My snippet code from the index blade file (jscript part at the bottom of blade file):
#push('js')
<script>
$(document).ready(function () {
var table1 = $("#userTable").DataTable({
responsive:true,
processing:true,
pagingType: 'full_numbers',
stateSave:false,
scrollY:true,
scrollX:true,
autoWidth: false,
ajax:"{{url('user/datatable')}}",
order:[0, 'desc'],
columns:[
{data:'first_name', name: 'First Name'},
{data:'last_name', name: 'First Name'},
{data:'email', name: 'E-Mail Address'},
{data:'action', name: 'Action', searchable: true, sortable:true},
]
});
...
</script>
#endpush
And finally where the data will be displayed (index blade file):
<table id="userTable" class="table table-bordered table-striped" data-toggle = "table1_" style = "width: 100%;">
<thead>
<tr>
<th class="all">First Name</th>
<th class="all">Last Name</th>
<th class="all">E-Mail Address</th>
<th class="all">Action</th>
</tr>
</thead>
<tfoot>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>E-Mail Address</th>
<th>Action</th>
</tr>
</tfoot>
</table>
I don't know what's wrong or where's the part that causes an error or problem because it doesn't show any response or data.
When i try to display the contents of this line by using dd():
$data = User::where('status', '=', 1);
It does not show any data from database but when I try this code that does the same it retrieves data from the database but still the DataTable error is appearing:
$data = DB::table('users')
->select('*')
->where('status', '=', 1)
->orderBy('id', 'desc')
->get();
I don't exactly know whether the data retrieval or data displaying
implementation or both is the problem.
What is the cause/s of the error/s or problem/s that results?

Script section works only in one view

I have a huge project in C# MVC. In one of the views, in index.cshtml, I have a code like this:
#model IEnumerable<Library.Models.Customer>
#{
ViewBag.Title = "Customers";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Klienci</h2>
<p>
#Html.ActionLink("Nowy klient", "New", "Customers", null, new { #class = "btn btn-primary" })
</p>
<table id ="customers" class="table table-bordered table-hover">
<thead>
<tr>
<th>Klient</th>
<th>Typ Czlonkostwa</th>
<th>Usun</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
#section scripts
{
<script>
$(document).ready(function () {
var table = $("#customers").DataTable({
ajax: {
url: "/api/customers",
dataSrc: ""
},
columns: [
{
data: "Name",
render: function(data, type, customer) {
return "<a href='/customers/edit/" + customer.Id + "'>" + customer.Name + "</a>";
}
},
{
data: "MembershipType.Name"
},
{
data: "Id",
render: function(data) {
return "<button class='btn-link js-delete' data-customer-id=" + data + ">Delete</button>";
}
}
]
});
$("#customers").on("click", ".js-delete",
function () {
var button = $(this);
if (confirm("Na pewno chcesz usunac?")) {
$.ajax({
url: "/api/customers/" + button.attr("data-customer-id"),
method: "DELETE",
success: function () {
//datatable methods - row, remove and draw
table.row(button.parents("tr")).remove().draw();
}
});
}
});
});
</script>
}
It works like a charm. But in another view, I have the code like this:
<table id="customers" class="table table-bordered table-hover">
<thead>
<tr>
<th>Ksiazka</th>
<th>Gatunek</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
#foreach (var book in Model)
{
<tr>
<td>#Html.ActionLink(book.Name, "Edit", "Books", new { id = book.Id }, null)</td>
<td>#book.Genre.Name</td>
<td>
<button class="btn-link" js-delete>Delete</button>
</td>
</tr>
}
</tbody>
#section scripts
{
<script>
$(document).ready(function() {
$("#customers .js-delete").on("click",
function() {
confirm("Sure?");
});
});
</script>
}
and it doesn't work. I mean, it compiles without any errors or warnings, but when I click Delete button nothing happens (should pop up confirm box).
What am I doing wrong?
If needed, I can provide whole code from these both views.
.js-delete means that "js-delete" is assumed to be a css class, while in the html it is an attribute. To search for elements with a particular attribute, you need "has attribute" selector:
$("#customers [js-delete]")

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

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 loop inside datatable columns declaration?

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.

Categories