v1.10 Datatables.net table will not load using ajax - examples at datatables.net did not help, nor did the documentation. The table displays, but says "No data available in table". I don't think it matters, but this is for an old MVC5 app that I'm doing a little maintenance on. I'm hoping someone can spot what's wrong?
HTML Table definition:
<table id="bob">
<thead>
<tr>
<th>License Type</th>
<th>Active</th>
<th>Pending</th>
<th>Other</th>
</tr>
</thead>
<tfoot>
<tr>
<th>License Type</th>
<th>Active</th>
<th>Pending</th>
<th>Other</th>
</tr>
</tfoot>
</table>
JavaScript Init:
$(function () {
var url = '#Url.Action("LicenseCountsReport", "Letters")';
$('#bob').DataTable({
ajax: {
dataSrc: '',
url: url,
columns: [
{ data: 'licensetype' },
{ data: 'activecount' },
{ data: 'pendingcount' },
{ data: 'othercount' }
]
}
});
});
Data Method & Associated Classes:
public class LicenseCountReportItem
{
public string licensetype { get; set; }
public string activecount { get; set; }
public string pendingcount { get; set; }
public string othercount { get; set; }
}
private class JsonDataResult
{
public List<LicenseCountReportItem> data { get; set; }
}
[HttpGet]
public JsonResult LicenseCountsReport()
{
JsonDataResult reportData = new JsonDataResult
{
data = new List<LicenseCountReportItem>()
};
try
{
List<LicenseCountReportItem> items = _lr.GetLicenseCountsReport();
if (items != null && items.Count > 0)
{
reportData = new JsonDataResult
{
data = items
};
return Json(reportData, JsonRequestBehavior.AllowGet);
}
return Json(reportData, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
Logger.Log(ex, LogLevel.ERROR);
return Json(reportData, JsonRequestBehavior.AllowGet);
}
}
JSON Response (formatted), an array of objects:
{
"data":[
{
"licensetype":"Commercial Apprentice Applicators",
"activecount":"130",
"pendingcount":"22",
"othercount":"99"
},
{
"licensetype":"Professional Applicators",
"activecount":"4239",
"pendingcount":"3314",
"othercount":"55147"
}
]
}
There are 2 problems I can see:
1 - The first problem: You have used the DataTables ajax option: dataSrc: ''. Instead, you should remove this option (or use its default value of data, as follows: dataSrc: 'data').
If you use dataSrc: '', you are telling DataTables that your JSON is an unnamed array - something like this:
[
{
"licensetype": "Commercial Apprentice Applicators",
"activecount": "130",
"pendingcount": "22",
"othercount": "99"
},
{
"licensetype": "Professional Applicators",
"activecount": "4239",
"pendingcount": "3314",
"othercount": "55147"
}
]
But that is not how your JSON is structured. Your array is nested inside a JSON object: { "data": [ ... ] }.
2 - The second problem: You have placed your columns option inside the ajax option. But the columns option needs to be at the same level as the ajax option:
$('#bob').DataTable({
ajax: {
url: url,
},
columns: [
{ data: 'licensetype' },
{ data: 'activecount' },
{ data: 'pendingcount' },
{ data: 'othercount' }
]
});
The columns option is independent of the ajax option.
Related
I am trying to store the employeeIds from the selected row of the table into the model column EmployeeReinstateVM.selectedEmployeeId from the click event of 'btnUpdate', each id must be stored to EmployeeReinstateVM.selectedEmployeeId. Currently the Ids are stored in to selectedEmployeeId hidden column as array string "23,24,25" So I am trying to store each employee id of the selected rows into the EmployeeReinstateVM.selectedEmployeeId from javascript to send the model into controller post method with selected employeeIds. I am looking for the help from someone. Here is the code
Model Class
public class EmployeeReinstateVM
{
public int EmployeeID { get; set; }
public string EmployeeName { get; set; }
public List<string> selectedEmployeeId { get; set; }
public IEnumerable<EmployeeModel> employees { get; set; }
}
Views
<style>
.selectable-row.selected {
background-color: #ddd;
}
</style>
#model EmployeeReinstateVM
foreach (var item in Model.employees)
{
<tr class="selectable-row
#(Model.selectedEmployeeId.Contains(item.EmployeeID.ToString()) ? "selected" :"")"
employee-id="#item.EmployeeID">
<td>#item.EmployeeID</td>
<td>#item.EmployeeName</td>
</tr>
}
<input hidden id="selectedEmployeeId" asp-for="selectedEmployeeId" name="selectedEmployeeId" value="">
<button type="submit" class="btn btn-primary form-control" id="btnUpdate" name="btnActivate" value="update">
Update
</button>
<script type="text/javascript">
$(document).ready(function() {
var employeeIds = [];
$(".selectable-row").click(function() {
$(this).toggleClass("selected");
var employeeId = $(this).attr('employee-id');
if ($(this).hasClass("selected")) {
employeeIds.push(employeeId);
//employeeIds.push($(this).attr('employee-id'));
} else {
employeeIds = employeeIds.filter(function(id) {
return id !== employeeId;
});
}
});
$("#btnUpdate").click(function() {
$("#selectedEmployeeId").val(employeeIds);
console.log($("#selectedEmployeeId").val());
});
})
This seems to be simpler - you need to store the result
$(".selectable-row").click(function() {
$(this).toggleClass("selected");
$("#selectedEmployeeId")
.val(
$("tr[employee-id].selected")
.map(function() { return $(this).attr("employee-id") })
.get()
.join(",")
);
});
store each employee id of the selected rows into the
EmployeeReinstateVM.selectedEmployeeId from javascript to send the
model into controller post method with selected employeeIds
Do you want to try the below code?
$("#btnSave").click(function () {
$("#selectedEmployeeId").val(employeeIds);
console.log($("#selectedEmployeeId").val());
$.ajax({
type: "POST",
url: "/Keepselected/ReinstateEmployee",
data: { "selectedEmployeeId": employeeIds },
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
success: function (response) {
alert(response);
}
});
});
result:
Newbie ALERT
Basically I have a web application that has a dropdown list. When you select an item in the drop-down list the table is drawn to show all the credentials that are tied to that drop-down option.
Problem: When running, everything functions properly except for the JavaScript piece that does not remove the line in the table, but deletes the record on the back-end. So once i refresh and go back to that credential type the one I deleted is gone.
I've tried a lot of different stuff, but i pretty new to JavaScript and C#, don't know if there is a better way of doing this. Probably supplied too much information but i rather too much than not enough! :)
Any help, tips, ideas are greatly appreciated.
Credential API Controller: Delete Function
[HttpDelete]
public IHttpActionResult DeleteCustomer(int id)
{
var credentialInDb = _context.Credentials.SingleOrDefault(c => c.Id == id);
if (credentialInDb == null)
return NotFound();
_context.Credentials.Remove(credentialInDb);
_context.SaveChanges();
return Ok();
}
Model for Credential
public class Credentials
{
public int Id { get; set; }
[Required]
[StringLength(255)]
public string Name { get; set; }
[Required]
[StringLength(255)]
public string Username { get; set; }
[Required]
[StringLength(255)]
public string Password { get; set; }
public string Website { get; set; }
public string Notes { get; set; }
public CredentialType CredentialType { get; set; }
[Display(Name = "Credential Type")]
public int CredentialTypeId { get; set; }
}
ViewModel for CredentialFormViewModel
This allows the selectedCredential variable for the page below
public class CredentialFormViewModel
{
public IEnumerable<CredentialType> CredentialTypes { get; set; }
public Credentials Credentials { get; set; }
public int SelectedCredentialTypeId { get; set; }
}
View that displays the DataTable:
#model Appp.ViewModels.CredentialFormViewModel
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Select a Credential Type</h2>
#Html.DropDownListFor(m => m.SelectedCredentialTypeId, new SelectList(Model.CredentialTypes, "Id", "Name"), "Select Credential Type", new { #class = "form-control", onchange = "SelectCredType()" })
<br/>
<table id="credentials" class="table table-bordered table-hover">
<thead>
<tr>
<th>Credential</th>
<th>Username</th>
<th>Password</th>
<th>Website</th>
<th></th>
</tr>
</thead>
<tbody>
</tbody>
</table>
#section scripts
{
<script>
function SelectCredType() {
var credId = $('#SelectedCredentialTypeId').val();
if ($.fn.dataTable.isDataTable("#credentials")) {
if (credId == "") {
var table = $("#credentials").DataTable();
table.destroy();
} else {
var table = $("#credentials").DataTable();
table.destroy();
SelectCredType();
}
} else {
$(document)
.ready(function() {
var table = $("#credentials")
.DataTable({
ajax: {
url: "/api/credentials?credentialTypeId=" + credId,
dataSrc: ""
},
columns: [
{
data: "name",
},
{
data: "username"
},
{
data: "password"
},
{
data: "website"
},
{
data: "id",
render: function(data, type, credentials) {
return "<button class='btn btn-primary btn-xs js-delete' data-credential-id=" + credentials.id + ">Delete</button>";
}
}
]
});
}
);
}
};
$("#credentials")
.on("click",
".js-delete",
function() {
var button = $(this);
bootbox.confirm("Are you sure you want to delete this?",
function(result) {
if (result) {
$.ajax({
url: "/api/Credentials/" + button.attr("data-credential-id"),
method: "DELETE",
sucess: function() {
table.row(button.parents("tr")).remove().draw();
}
});
}
});
});
</script>
}
First issue
Your JavaScript code does not work because the table variable is undefined within your delete function.
There are many ways you could approach to fix that. But first you will need to get your head around variable scopes in JavaScript.
Your simplest solution is to make table a globally-scoped variable that way you can access the instance from any function you create. So instead of defining it here:
...
$(document)
.ready(function() {
var table = $("#credentials")
...
Move it up to the top of your script file:
var table;
function SelectCredType() {
...
$(document)
.ready(function() {
table = $("#credentials")
...
}
Now when you access it from your Delete function, it will be defined.
Note: I would also change the name of the table variable to something else as global variables in JavaScript will conflict with any script you import which can lead to a debugging nightmare. Best to name it something that will be most likely unique, eg. coberlinTable.
Second Issue
I don't know if you did a cut and past error, but you have misspelled success in your ajax Delete function.
After seeing a lot of code samples, I cant make a simple datatable using Jquery Datatables and MVC.
I got the error
My controller is this
public class DataTableController : Controller
{
// GET: DataTable
public ActionResult Index()
{
return View();
}
public ActionResult GetData()
{
var registros = new List<PruebaClass>();
var pruebaClass1 = new PruebaClass
{
Race = "Aliens",
Year = 1990,
Total = 50
};
var pruebaClass2 = new PruebaClass
{
Race = "MArcianos",
Year = 200,
Total = 20
};
registros.Add(pruebaClass1);
registros.Add(pruebaClass2);
var resultado = Json(new { aaData = registros.ToList() }, JsonRequestBehavior.AllowGet);
return resultado;
}
public class PruebaClass
{
public string Race { get; set; }
public int Year { get; set; }
public int Total { get; set; }
}
}
My view is this
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<table id="miTable">
<thead>
<tr>
<th>Race</th>
<th>Year</th>
<th>Total</th>
</tr>
</thead>
</table>
#section Scripts{
<link rel="stylesheet" type="text/css" href="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.0/css/jquery.dataTables_themeroller.css">
<link rel="stylesheet" type="text/css" href="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.0/css/jquery.dataTables.css">
<script type="text/javascript" charset="utf8" src="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.0/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="~/Scripts/MyDataTablejs.js"></script>
}
And my javascript file is this
$(document).ready(function () {
$('#miTable').DataTable(
{
"sAjaxSource": "../DataTable/GetData",
"columns": [
{ "Data": "Race", "autoWidth": true },
{ "Data": "Year", "autoWidth": true },
{ "Data": "Total", "autoWidth": true }
]
});
});
I can reach the ActionResult, and my view shows two rows but the content of each cell is null. And I got the awfull error Datatables warning (table id= 'miTable')Requested unknown parameter '0' from the datasource '0' .
Im pretty sure that the problem is the source (maybe the JSON format) and the column name mapping, but I cant figure out what is.
Any help?
Shame on me. Finally I matched the columns definition with apropiate options in the jquery file. I knew that I was missing something. All I need to do was to use the "aocolumns" and "mDataProp"
this code solves all
$(document).ready(function () {
$('#miTable').DataTable(
{
"sAjaxSource": "../DataTable/GetData",
"aoColumns": [
{ "mDataProp": "Race", "autoWidth": true },
{ "mDataProp": "Year", "autoWidth": true },
{ "mDataProp": "Total", "autoWidth": true }
]
});
});
To preface this question, I will admit that I know nothing about javascript and related topics. I am trying to have a table be created and filled out based on a button push. If I pass the data directly into the ViewModel, it displays correctly, so I know the table is working right. Here is the JQuery request:
<input type="button" id="RootsBtn" value="Go"/>
<script language="javascript" type="text/javascript">
$(function () {
$("#RootsBtn").click(function () {
$.ajax({
cache: false,
type: "GET",
url: "#(Url.RouteUrl("GetApplications"))",
data: {},
success: function (data) {
alert(data.length);
$('#AppTableID').show();
},
error: function (xhr, ajaxOptions, throwError) {
alert("Error");
$('#AppTableID').hide();
}
});
});
});
</script>
I'm basing this code loosely on code I'm using to populate a dropdown list. I know the data is being grabbed properly because the alert(data.length); line shows the proper number of objects in my list.
The dropdown code included a $.each line. I have tried using variants of this and nothing has worked for me.
How would I get the data saved into my ViewModel so that it can be displayed?
EDIT: Adding more details
This is the Table display in my view:
<div id="AppTableID">
<table id="dashboard">
<thead>
<th>
#Html.LabelFor(model => model.apps.FirstOrDefault().AppStringID)
</th>
<th>
#Html.LabelFor(model => model.apps.FirstOrDefault().ApplicationCategoryID)
</th>
<th>
#Html.LabelFor(model => model.apps.FirstOrDefault().Description)
</th>
</thead>
#foreach (var item in Model.apps ?? new List<Application> { null })
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.AppStringID)
</td>
<td>
#Html.DisplayFor(modelItem => item.ApplicationCategoryID)
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
</tr>
}
</table>
</div>
This is my viewmodel which is passed into the view:
public class HomeViewModel
{
public HomeViewModel()
{
apps = new List<Application>();
}
public IEnumerable<Application> apps { get; set; }
}
This is the Application class:
public class Application
{
public long ID { get; set; }
public string AppStringID { get; set; }
public int? ApplicationCategoryID { get; set; }
public string Description { get; set; }
}
This is GetApplications: (appService.ToList() correctly gets the list of data. This has been well tested.)
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult GetApplications()
{
var apps = appService.ToList();
if (apps == null)
{
return Json(null, JsonRequestBehavior.AllowGet);
}
return Json(apps, JsonRequestBehavior.AllowGet);
}
In the success function of your ajax call
$.ajax({
....
success: function (data) {
$.each(data, function(index, item) {
var row = $('<tr></tr>'); // create new table row
row.append($('<td></td>').text(item.AppStringID));
row.append($('<td></td>').text(item.ApplicationCategoryID));
row.append($('<td></td>').text(item.Description));
$('#dashboard').append(row); // add to table
});
$('#AppTableID').show();
},
....
});
Notes: You should probably include a tbody element as a child of your table and add the rows to that. Your foreach loop only needs to be #foreach (var item in Model.apps) {.. (the collection has been initialized in the constructor). You also don't need the if (apps == null) {..} condition in the GetApplications method
My Kendo UI TreeView is not getting the returned JSON objects added to the treeview.
I can see from the controller method that gets called that the Json being given to the DataSource looks like this (but with more files and folders)
{"NodeID":-842352767,
"Name":"/",
"Folders":[{"NodeID":1804712307,"Name":"/$Recycle.Bin","Folders":null,"Files":null},{"NodeID":-582712839,"Name":"/Windows","Folders":null,"Files":null}],
"Files":["/.rnd","/msdia80.dll"]}
My view is as follows:
#model ProjName.Models.BrowseNode
<div id ="wrapper">
<h1>Browser</h1>
<div id="treeview" style="float:left;margin: 40px;">
</div>
</div>
<script>
function populateTreeView() {
var remoteDataSource = new kendo.data.HierarchicalDataSource({
type: "json",
transport: {
read: "FileBrowser/GetHierarchy"
},
schema: {
model: {
id: "NodeID",
text: "Name",
expanded: false,
children: "Folders",
},
}
});
$("#treeview").kendoTreeView({
dataSource: remoteDataSource,
dataTextField: "Name"
});
}
$(document).ready(function () {
populateTreeView();
});
With BrowseNode defined as:
public class BrowseNode
{
public int NodeID {
get
{
if (null == Name)
return default(int);
return Name.GetHashCode();
}
}
public string Name { get; set; }
public List<BrowseNode> Folders { get; set; }
public List<string> Files { get; set; }
}
Anything obviously wrong or any tips for debugging this sort of thing?
It turned out my JSON wasn't what the DataSource wanted. It should have been an array returned at the top level, so the JSON is surrounded by [ ] brackets as follows:
[{"NodeID":-842352767, "Name":"/", "Folders":[{"NodeID":1804712307,"Name":"/$Recycle.Bin","Folders":null,"Files":null},{"NodeID":-582712839,"Name":"/Windows","Folders":null,"Files":null}], "Files":["/.rnd","/msdia80.dll"]}]