Related
This is my working cshtml with ajax. Currently $(function () { loaddata();}) is what initializes the DataTable and "url": '/LoadData'() posts to the controller. But I need it to Post only when validation passes. I still need the Datatable to initialize though. When the document is ready I would like to initialize the Datatable just not LoadData. Post should automatically happen when validation passes.
button onclick="test()">RefreshData</button>
<table id="tblList" class="table table-striped table-bordered" style="width:100%">
<thead>
<tr>
<th>a</th>
<th>b</th>
<th>c</th>
<th>d</th>
</tr>
</thead>
</table>
js:
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.1/jquery-ui.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.css">
function test() {
$('#tblList').DataTable().ajax.reload();
}
function validationfailure() {
//$('#firstname').val()=="";
return 'please enter a valid name'
}
function loaddata() {
var data = {};
data.id = $("#id").val();
$('#tblList').DataTable({
destroy: true,
ajax: {
"type": "POST",
"url": '/LoadData',
"dataType": "json",
"data": function(d) {
d.id = $("#id").val();
}
},
columns: [
{ "data": "a", responsivePriority: 1, "searchable": true },
{ "data": "b", responsivePriority: 2, "searchable": true },
{ "data": "c", responsivePriority: 3, "searchable": true },
{ "data": "d", responsivePriority: 4, "searchable": true },
],
});
};
$(function() {
if(!validationfailure)
loaddata();
})
action:
[HttpPost]
[Route("LoadData")]
public IActionResult GetFinanceiro(SearchModel s)
{
List<DataTableModel> l = new List<DataTableModel> {
new DataTableModel{ a="a1"+s.Id,b="b1"+s.Id,c="c1"+s.Id,d="d1"+s.Id},
new DataTableModel{ a="a2",b="b2",c="c2",d="d2"},
new DataTableModel{ a="a3",b="b3",c="c3",d="d3"},
new DataTableModel{ a="a4",b="b4",c="c4",d="d4"},
};
return Json(new { data = l });
}
newbie here. My target is to store my fetched data in my array. T
This is my script. This script function is to join 2 data in 1 if they have the same level. For example player 1 has level 1, player 6 has level 1 also, which means that Player 1 and player 6 will be joined in 1 array. This current script is static, it is not dynamic yet. My target is to store my fetched data here rather than the static ones. Thank you in advance, any help will be appreciated.
const players = [
{
id: 1,
name: 'player1',
level: '1',
},
{
id: 2,
name: 'player2',
level: '2',
},
{
id: 3,
name: 'player3',
level: '3',
},
{
id: 4,
name: 'player4',
level: '3',
},
{
id: 5,
name: 'player5',
level: '2',
},
{
id: 6,
name: 'player6',
level: '1',
}
];
const matching = (list, keyGetter) => {
let mapping = {};
const map = new Map();
list.forEach((item) => {
const key = keyGetter(item);
const collection = map.get(key);
if (!collection) {
map.set(key, [item]);
} else {
collection.push(item);
}
});
Array.from(map).map(([key, value]) => Object.assign(mapping, { [key]: value }));
return mapping
}
const result = matching(players, ({ level}) => { return level});
console.log("RESULT", result);
this is the result of the above script
In this function, this is how i fetch my data. My target is to store my fetched data to the array i made above const = players
views:
<table id="table_player" class="table table-bordered table-hover" cellspacing="0">
<thead>
<tr>
<th>ID</th>
<th>Player</th>
<th>Level</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
ajax:
$(document).ready(function() {
//datatables
table = $('#table_player').DataTable({
dom: 'lBfrtip',
buttons: [
'print', 'csv', 'copy', 'excel', 'pdfHtml5'
],
"processing": false, //Feature control the processing indicator.
"serverSide": true, //Feature control DataTables' server-side processing mode.
"order": [], //Initial no order.
// Load data for the table's content from an Ajax source
"ajax": {
"url": "<?php echo site_url('controller/ajax_list')?>",
"type": "POST",
"data": function (dateParams) {
return $.extend( { "start": dateParams.start,
"end": dateParams.end,}, dateParams, {
});
},
},
//Set column definition initialization properties.
"columnDefs": [
{
"targets": [ 0 ], //first column
"orderable": false, //set not orderable
},
{
"targets": [ -1 ], //last column
"orderable": false, //set not orderable
},
],
});
});
Controller:
public function ajax_list()
{
$list = $this->model->get_datatables();
$data = array();
$no = $_POST['start'];
foreach ($list as $person) {
$no++;
$row = array();
$row[] = $person->id;
$row[] = $person->player;
$row[] = $person->level;
$data[] = $row;
}
$output = array(
"draw" => $_POST['draw'],
"recordsTotal" => $this->model->count_all(),
"recordsFiltered" => $this->model->count_filtered(),
"data" => $data,
);
//output to json format
echo json_encode($output);
}
Model:
var $table = 'tbl_player';
var $column_order = array(null,'id','player','level');
var $order = array('id' => 'desc');
var $column_search = array('id','player','level');
//set column field database for datatable orderable //set column field database for datatable searchable just firstname , lastname , address are searchable var $order = array('id' => 'desc'); // default order
private function _get_datatables_query()
{
$this->db->from($this->table);
$i = 0;
foreach ($this->column_search as $item) // loop column
{
if($_POST['search']['value']) // if datatable send POST for search
{
if($i===0) // first loop
{
$this->db->group_start(); // open bracket. query Where with OR clause better with bracket. because maybe can combine with other WHERE with AND.
$this->db->like($item, $_POST['search']['value']);
}
else
{
$this->db->or_like($item, $_POST['search']['value']);
}
if(count($this->column_search) - 1 == $i) //last loop
$this->db->group_end(); //close bracket
}
$i++;
}
if(isset($_POST['order'])) // here order processing
{
$this->db->order_by($this->column_order[$_POST['order']['0']['column']], $_POST['order']['0']['dir']);
}
else if(isset($this->order))
{
$order = $this->order;
$this->db->order_by(key($order), $order[key($order)]);
}
}
function get_datatables()
{
$this->_get_datatables_query();
if($_POST['length'] != -1)
$this->db->limit($_POST['length'], $_POST['start']);
$query = $this->db->get();
return $query->result();
}
function count_filtered()
{
$this->_get_datatables_query();
$query = $this->db->get();
return $query->num_rows();
}
public function count_all()
{
$this->db->from($this->table);
return $this->db->count_all_results();
}
I Would like to use server side rendering while fetching data from server. When I click paging button on datatable I want to upload new data from server. So I used below codes for this. But I get this error
"DataTables warning: table id=MyDataTable - Requested unknown parameter 'CompanyName' for row 0, column 0. For more information about this error, please see http://datatables.net/tn/4" always.
public class HomeController : Controller
{
public async Task<ActionResult> Index()
{
return View();
}
public async Task<JsonResult> GetEmployeeRecord(DataTablesParam param)
{
var a = await new CompanyService().Getlisttt(x => x.Phone1 == "12345688");
List<CompanyViewObject> List = new List<CompanyViewObject>();
int pageNo = 1;
if (param.iDisplayStart >= param.iDisplayLength)
{
pageNo = (param.iDisplayStart / param.iDisplayLength) + 1;
}
int totalCount = 0;
totalCount = a.Count();
List = a.Skip((pageNo - 1) * param.iDisplayLength).Take(param.iDisplayLength).Select(x => new CompanyViewObject
{
CompanyName = x.CompanyName,
Description = x.Description,
GlobalCompanyID = x.GlobalCompanyID,
Phone1 = x.Phone1,
CompanyTypeName = x.CompanyTypeName,
CompanyOwnershipName = x.CompanyOwnershipName,
CompanyIndustryName = x.CompanyIndustryName,
ParentID = x.ParentID,
Website = x.Website,
EMail = x.EMail,
Phone2 = x.Phone2,
Fax = x.Fax,
Confirmed = x.Confirmed,
Active = x.Active
}).ToList();
return Json(new
{
aaData = List,
sEcho = param.sEcho,
iTotalDisplayRecords = totalCount,
iTotalRecords = totalCount
});
}
}
My view page is this
<div class="row pt-10">
<div class="col-md-12">
<table class="display" id="MyDataTable">
<thead>
<tr>
<th>
CompanyName
</th>
<th>
Description
</th>
<th>
GlobalCompanyID
</th>
<th>
Phone1
</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
<script>
$(document).ready(function () {
// $("#MyDataTable").DataTable();
BindDataTable();
})
var BindDataTable = function (response) {
var x;
$("#MyDataTable").DataTable({
"bServerSide": true,
"sAjaxSource": "/Home/GetEmployeeRecord",
"fnServerData": function (sSource, aoData, fnCallback) {
$.ajax({
type: "Get",
data: aoData,
url: sSource,
success: fnCallback,
})
console.log(fnCallback);
},
"columns": [
{ "data": "CompanyName" },
{ "data": "Description" },
{ "data": "Phone1" },
{ "data": "GlobalCompanyID" },
]
});
console.log(x);
}
</script>
Thanks in advance
Edit=when I change code like this I dont get error but I still cant get values on table
"columns": [
{ "data": 'aaData["CompanyName"]' },
{ "data": 'aaData["Description"]' },
{ "data": 'aaData["Phone1"]'},
{ "data": 'aaData["GlobalCompanyID"]' },
],
My ajax return is object is like this
{"sEcho":1,"iTotalDisplayRecords":137,"iTotalRecords":137,"aaData":[{"globalCompanyID":13,"companyTypeName":"Other","companyOwnershipName":"Other","companyIndustryName":"Engineering","parentID":0,"companyName":"ffff","website":"www.youtube.com","eMail":"support#micromarin.com","phone1":"12345688","phone2":"333333333333","fax":"7788554422","description":"Yeni kurulan bir firma","confirmed":true,"active":false},{"globalCompanyID":14,"companyTypeName":"Prospect","companyOwnershipName":"Public","companyIndustryName":"Agriculture","parentID":0,"companyName":"Company 1","website":"www.youtube.com","eMail":"support#micromarin.com","phone1":"12345688","phone2":"333333333333","fax":"7788554422","description":"Yeni kurulan bir firma","confirmed":true,"active":true},{"globalCompanyID":15,"companyTypeName":"Prospect","companyOwnershipName":"Public","companyIndustryName":"Agriculture","parentID":0,"companyName":"Company 2","website":"www.youtube.com","eMail":"support#micromarin.com","phone1":"12345688","phone2":"333333333333","fax":"7788554422","description":"Yeni kurulan bir firma","confirmed":true,"active":true},{"globalCompanyID":16,"companyTypeName":"Prospect","companyOwnershipName":"Public","companyIndustryName":"Agriculture","parentID":0,"companyName":"Company 3","website":"www.youtube.com","eMail":"support#micromarin.com","phone1":"12345688","phone2":"333333333333","fax":"7788554422","description":"Yeni kurulan bir firma","confirmed":true,"active":true},{"globalCompanyID":17,"companyTypeName":"Prospect","companyOwnershipName":"Public","companyIndustryName":"Agriculture","parentID":0,"companyName":"Company 4","website":"www.youtube.com","eMail":"support#micromarin.com","phone1":"12345688","phone2":"333333333333","fax":"7788554422","description":"Yeni kurulan bir firma","confirmed":true,"active":true},{"globalCompanyID":18,"companyTypeName":"Prospect","companyOwnershipName":"Public","companyIndustryName":"Agriculture","parentID":0,"companyName":"Company 5","website":"www.youtube.com","eMail":"support#micromarin.com","phone1":"12345688","phone2":"333333333333","fax":"7788554422","description":"Yeni kurulan bir firma","confirmed":true,"active":true},{"globalCompanyID":19,"companyTypeName":"Prospect","companyOwnershipName":"Public","companyIndustryName":"Agriculture","parentID":0,"companyName":"Company 6","website":"www.youtube.com","eMail":"support#micromarin.com","phone1":"12345688","phone2":"333333333333","fax":"7788554422","description":"Yeni kurulan bir firma","confirmed":true,"active":true},{"globalCompanyID":20,"companyTypeName":"Prospect","companyOwnershipName":"Public","companyIndustryName":"Agriculture","parentID":0,"companyName":"Company 7","website":"www.youtube.com","eMail":"support#micromarin.com","phone1":"12345688","phone2":"333333333333","fax":"7788554422","description":"Yeni kurulan bir firma","confirmed":true,"active":true},{"globalCompanyID":21,"companyTypeName":"Prospect","companyOwnershipName":"Public","companyIndustryName":"Agriculture","parentID":0,"companyName":"Company 8","website":"www.youtube.com","eMail":"support#micromarin.com","phone1":"12345688","phone2":"333333333333","fax":"7788554422","description":"Yeni kurulan bir firma","confirmed":true,"active":true},{"globalCompanyID":22,"companyTypeName":"Prospect","companyOwnershipName":"Public","companyIndustryName":"Agriculture","parentID":0,"companyName":"Company 9","website":"www.youtube.com","eMail":"support#micromarin.com","phone1":"12345688","phone2":"333333333333","fax":"7788554422","description":"Yeni kurulan bir firma","confirmed":true,"active":true}]}
I added below code to startup.cs in public void ConfigureServices(IServiceCollection services) and problem solved I guess controller had not returned json format before. After update controller return Json
Services.AddMvc().AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver())
This is a basic structure of server side Datatable,
function datatable(sSource, aoData, fnCallback){
var table = $('#tableID').DataTable({
dom: dom,
buttons : [
'excel', 'pdf', 'print',
],
lengthMenu: [[10, 25, 50, -1], [10, 25, 50, "All"]],
serverSide: true,
processing: true,
ajax: {
"url": sSource,
"type": "GET",
"data": aoData,
success: fnCallback
},
});
}
Ajax request is of GET type, data_function is there is you need to pass any parameter else leave that.
Hope this helps!
I added below code to startup.cs and the promlem is solved;
Services.AddMvc().AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver())
I have a Linq query that is returning data in 900 - 919ms through EF Core (over VPN). However, once the data is returned it is taking an age (20-30 seconds) to render the HTML table. The dataset is about 18,000 rows with 8 columns and I have implemented DataTables to paginate, filter and export. The dataset itself is comprised of text only.
I have been trying to profile those 20-30 seconds to no great success, I just can't seem to find the route of the issue.
Has anyone faced similar issues?
Can anyone recommend a good debug methodology to understand the cause of delay?
I have logging enabled and that is not telling me anything of use, Application Insights in VS is not available to me.
Many thanks.
Update
Below is method.
public async Task<ActionResult> ExportGrid()
{
var result = await dbcontext.Timesheet.AsNoTracking()//.Take(100)
//.Include(t => t.Program)
//.ThenInclude(p => p.Client)
//.Include(t => t.Task)
//.Include(t => t.Person)
.Where(t => !t.Deleted)
.Select(t => new TimesheetDataViewModel
{
Id = t.Id,
ClientName = t.Program.Client.Name,
ProgramName = t.Program.Name,
TaskType = t.Task.Name,
TaskName = t.Name,
TaskDescription = t.Description,
TaskStart = t.TaskStart,
TaskEnd = t.TaskEnd,
Minutes = t.Minutes,
Person = t.Person.Firstname + ' ' + t.Person.Surname
}).ToListAsync();
return View(result);
}
Below is the DataTables code
var _tableId = $('#datatable_timesheet');
var _orderColumns = [1];
var _searchableColumns = [0,1,2];
var _defaultSort = [1, "asc"];
$(document).ready(function () {
_tableId.DataTable({
paging: true,
ordering: true,
info: false,
responsive: true,
deferRender: false,
dom: '<"row"<"col-sm-3"l><"col-sm-6 text-center"B"><"col-sm-3"f>><"row"<"col-sm-12"tr>><"row"<"col-sm-5"i><"col-sm-7"p>>',
buttons: true,
lengthMenu: [
[5, 15, 20, -1],
[5, 15, 20, "All"] // change per page values here
],
//pagingType: "bootstrap_full_number",
language: {
"lengthMenu": " _MENU_ records",
"paginate": {
"previous": "Prev",
"next": "Next",
"last": "Last",
"first": "First"
}
},
columnDefs: [{ // set default column settings
'orderable': true,
'targets': _orderColumns
}, {
"searchable": true,
"targets": _searchableColumns
}]
//order: _defaultSort // set first column as a default sort by asc*/
});
});
it will paginate on client side
for better performance you can use server side pagination - for e.g. refer article to use server side pagination.
https://www.codeproject.com/Tips/1011531/Using-jQuery-DataTables-with-Server-Side-Processin
I found this quite hard to get my head round and in case anyone else is, below is how I finally got everything working except sort for an application built using .Net Core 1.1 and Entity.Framework.Core
HTML
<table class="table table-striped table-bordered table-hover" id="exportGrid">
<thead>
<tr>
<th>
Client Name
</th>
<th>
Program Name
</th>
<th>
Person
</th>
<th>
Minutes
</th>
<th>
Task Name
</th>
<th>
Task Description
</th>
<th>
Task Type
</th>
<th>
Task Start
</th>
<th>
Task End
</th>
</tr>
</thead>
</table>
JS and AJAX
$('#exportGrid').DataTable({
processing: true,
serverSide: true,
ajax: { "url": "TimesheetDataJsonObjectArray", "type": "POST" },
columns: [
{ "data": "clientName" },
{ "data": "programName" },
{ "data": "person" },
{ "data": "minutes" },
{ "data": "taskName" },
{ "data": "taskDescription" },
{ "data": "taskType" },
{ "data": "taskStart" },
{ "data": "taskEnd" }],
pageLength: 15,
paging: true,
ordering: true,
info: true,
responsive: true,
deferRender: false,
dom: '<"row"<"col-sm-3"l><"col-sm-6 text-center"B"><"col-sm-3"f>><"row"<"col-sm-12"tr>><"row"<"col-sm-5"i><"col-sm-7"p>>',
buttons: true,
lengthMenu: [
[5, 15, 20, -1],
[5, 15, 20, "All"]
]
});
Controller
[HttpPost]
public async Task<ActionResult> TimesheetDataJsonObjectArray(int draw, int start, int length)
{
var formData = HttpContext.Request.Form;
string search = formData["search[value]"];
var q = dbcontext.Timesheet.Where(t => !t.Deleted);
if(!String.IsNullOrEmpty(search))
{
q = q.Where(t => t.Person.Surname.Contains(search));
}
var b = await q
.Select(t => new TimesheetDataViewModel
{
Id = t.Id,
ClientName = t.Program.Client.Name,
ProgramName = t.Program.Name,
TaskType = t.Task.Name,
TaskName = t.Name,
TaskDescription = t.Description,
TaskStart = t.TaskStart,
TaskEnd = t.TaskEnd,
Minutes = t.Minutes,
Person = t.Person.Firstname + ' ' + t.Person.Surname
}).ToListAsync();
var result = b.Skip(start).Take(length);
DataTableData a = new DataTableData();
a.data = result.ToList();
a.draw = draw;
a.recordsTotal = q.Count();
a.recordsFiltered = q.Count();
return Json(a);
}
I have two types of maps of Nepal (districts map of Nepal and ecological map of Nepal). I have two data sets for each of the above type. I am trying to create a visualization where users can first choose what type of map they want and then later what data they want to be visualized. (using dropdowns).
These are the codes for dropdowns.
<select id="changeMap">
<option>Change Map</option>
<option value="ecoMap">Ecological Region</option>
<option value="world_mill_en">Districts</option>
</select>
<select id="changedata">
<option>Change Data</option>
<option value="Caste 1">CASTE 1</option>
<option value="Caste 2">CASTE 2</option>
</select>
This is the jvector Map function.
<div id="container"></div>
<script>
var vmap = '<div id="vmap" style="width: 600px; height: 400px;"></div>';
$('#changeMap').on('change', function () {
var _map = $(this).val();
$('#vmap').remove();
$('#container').append(vmap);
$('#vmap').vectorMap({
map: _map,
backgroundColor: '#000000',
enableZoom: true,
regionsSelectable : false,
series: {
regions: [{
values: data,
scale: ['#fffad6', '#d05300'],
normalizeFunction: 'polynomial'
}]
}});
});
</script>
Now, how do I make this drop- drop down combination work to visualize?
Thanks!
I guess u want a complete dynamic implementation of the map. I used the same for creating Australia's map with dynamic regions plotted on it on the fly.
Initially create the jvectormap object with path attribute left empty as shown below:
var auJSON = {
"insets": [
{
"width": 900.0,
"top": 0,
"height": 850.8001894248416,
"bbox": [
{
"y": 1125139.6460741498,
"x": 12575140.762771795
},
{
"y": 5412845.645305354,
"x": 17110794.900221862
}],
"left": 0
}
],
"paths": {
},
"height": 850.8001894248416,
"projection":
{
"type": "merc",
"centralMeridian": 0.0
},
"width": 900.0
};
Now, on click on any of the option you have to insert the objects in the path attribute dynamically and finally render the map. I created an array of objects below.
d3.select("#regionSVG").selectAll("path")
.each(function () {
var obj = {
"path": $(this).attr("d"),
"name": $(this).attr("name"),
"id": this.id
}
that.regionPathArray.push(obj);
});
Now i passed on this array to fill in the empty path attribute as below.
initRegionLoading(that.regionPathArray);
function initRegionLoading(arr) {
var initialJSON = auJSON;
for (var i = 0; i < arr.length; i++) {
initialJSON.paths[arr[i].name] = arr[i];
}
$.fn.vectorMap('addMap', 'au_reg_en', initialJSON);
}
And then i displayed the map.
this.ausie_map = new jvm.WorldMap({
map: 'au_reg_en',
container: $('#auMap_' + that.zoomLevel),
});
That solves my problem. Hope it does yours too.