jQuery Datatables - footerCallback sum columns, issues with table total - datatables

ive created a function that I can call on columns that I wish to sum up using the below. however the total (table total) entry for column 9 is always zero. the page total seems to work. and the page total and table total for column 9 works also.
"footerCallback": function ( row, data, start, end, display ) {
var api = this.api(), data;
// Remove the formatting to get integer data for summation
var intVal = function ( i ) {
return typeof i === 'string' ?
i.replace(/[\£,]/g, '')*1 :
typeof i === 'number' ?
i : 0;
};
var column_sum = function (col) {
// Total over all pages
total = api
.column(col)
.data()
.reduce( function (a, b) {
return intVal(a) + intVal(b);
}, 0 );
// Total over this page
pageTotal = api
.column(col, { page: 'current'} )
.data()
.reduce( function (a, b) {
return intVal(a) + intVal(b);
}, 0 );
return accounting.formatMoney(pageTotal) +' ('+ accounting.formatMoney(total) +' total)'
};
// Update footer
$( api.column(6).footer()).html(
column_sum(6)
);
$( api.column(9).footer()).html(
column_sum(9)
);
}
EDIT
I have added some sanitised data. currently the page total works for the first column and second columns.
The all pages total does not work. i.e each time I filter by the column header I should see the total across each page
<table width="100%" class="table table-striped table-bordered table-hover dataTable no-footer dtr-inline" id="circuit_list"
role="grid" style="width: 100%;">
<thead>
<tr>
<th>Info</th>
<th>Type</th>
<th>Cost PM</th>
<th>Term</th>
<th>Remaining Term</th>
<th>Remaining Cost</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<a href="/circuits/edit/238/1/all_cl" class="btn btn-primary btn-circle">
<i class="fa fa-list"></i>
</a>
</td>
<td>Fibre</td>
<td>£950.00</td>
<td>12</td>
<td>0</td>
<td>£0.00</td>
</tr>
<tr>
<td>
<a href="/circuits/edit/238/2/all_cl" class="btn btn-primary btn-circle">
<i class="fa fa-list"></i>
</a>
</td>
<td>Fibre</td>
<td>£950.00</td>
<td>12</td>
<td>0</td>
<td>£0.00</td>
</tr>
<tr>
<td>
<a href="/circuits/edit/333/101/all_cl" class="btn btn-primary btn-circle">
<i class="fa fa-list"></i>
</a>
</td>
<td>MPLS</td>
<td>£1791.33</td>
<td>12</td>
<td>11</td>
<td>£19,704.63</td>
</tr>
<tr>
<td>
<a href="/circuits/edit/334/101/all_cl" class="btn btn-primary btn-circle">
<i class="fa fa-list"></i>
</a>
</td>
<td>MPLS</td>
<td>£100.00</td>
<td>12</td>
<td>11</td>
<td>£1,100.00</td>
</tr>
<tr>
<td>
<a href="/circuits/edit/235/1/all_cl" class="btn btn-primary btn-circle">
<i class="fa fa-list"></i>
</a>
</td>
<td>MPLS</td>
<td>£593.33</td>
<td>36</td>
<td>15</td>
<td>£8,899.95</td>
</tr>
<tr>
<td>
<a href="/circuits/edit/317/82/all_cl" class="btn btn-primary btn-circle">
<i class="fa fa-list"></i>
</a>
</td>
<td>Fibre</td>
<td>£103.00</td>
<td>3</td>
<td>0</td>
<td>£0.00</td>
</tr>
<tr>
<td>
<a href="/circuits/edit/229/2/all_cl" class="btn btn-primary btn-circle">
<i class="fa fa-list"></i>
</a>
</td>
<td>MPLS</td>
<td>£373.33</td>
<td>36</td>
<td>11</td>
<td>£4,106.63</td>
</tr>
<tr>
<td>
<a href="/circuits/edit/233/1/all_cl" class="btn btn-primary btn-circle">
<i class="fa fa-list"></i>
</a>
</td>
<td>DSL</td>
<td>£1837.66</td>
<td>60</td>
<td>6</td>
<td>£11,025.96</td>
</tr>
<tr>
<td>
<a href="/circuits/edit/234/1/all_cl" class="btn btn-primary btn-circle">
<i class="fa fa-list"></i>
</a>
</td>
<td>DSL</td>
<td>£373.34</td>
<td>36</td>
<td>15</td>
<td>£5,600.10</td>
</tr>
<tr>
<td>
<a href="/circuits/edit/243/5/all_cl" class="btn btn-primary btn-circle">
<i class="fa fa-list"></i>
</a>
</td>
<td>DSL</td>
<td>£373.34</td>
<td>36</td>
<td>15</td>
<td>£5,600.10</td>
</tr>
<tr>
<td>
<a href="/circuits/edit/244/4/all_cl" class="btn btn-primary btn-circle">
<i class="fa fa-list"></i>
</a>
</td>
<td>MPLS</td>
<td>£373.34</td>
<td>36</td>
<td>12</td>
<td>£4,480.08</td>
</tr>
<tr>
<td>
<a href="/circuits/edit/324/83/all_cl" class="btn btn-primary btn-circle">
<i class="fa fa-list"></i>
</a>
</td>
<td>4G</td>
<td>£103.00</td>
<td>3</td>
<td>0</td>
<td>£0.00</td>
</tr>
<tr>
<td>
<a href="/circuits/edit/2/6/all_cl" class="btn btn-primary btn-circle">
<i class="fa fa-list"></i>
</a>
</td>
<td>4G</td>
<td>£41.50</td>
<td>12</td>
<td>0</td>
<td>0.00</td>
</tr>
<tr>
<td>
<a href="/circuits/edit/57/18/all_cl" class="btn btn-primary btn-circle">
<i class="fa fa-list"></i>
</a>
</td>
<td>4G</td>
<td>£45.00</td>
<td>12</td>
<td>0</td>
<td>£0.00</td>
</tr>
<tr>
<td>
<a href="/circuits/edit/113/35/all_cl" class="btn btn-primary btn-circle">
<i class="fa fa-list"></i>
</a>
</td>
<td>Fibre</td>
<td>£45.00</td>
<td>12</td>
<td>0</td>
<td>£0.00</td>
</tr>
<tr>
<td>
<a href="/circuits/edit/218/71/all_cl" class="btn btn-primary btn-circle">
<i class="fa fa-list"></i>
</a>
</td>
<td>4G</td>
<td>£57.00</td>
<td>12</td>
<td>0</td>
<td>£0.00</td>
</tr>
<tr>
<td>
<a href="/circuits/edit/264/71/all_cl" class="btn btn-primary btn-circle">
<i class="fa fa-list"></i>
</a>
</td>
<td>MPLS</td>
<td>£45.00</td>
<td>12</td>
<td>0</td>
<td>£0.00</td>
</tr>
<tr>
<td>
<a href="/circuits/edit/269/61/all_cl" class="btn btn-primary btn-circle">
<i class="fa fa-list"></i>
</a>
</td>
<td>DSL</td>
<td>£45.00</td>
<td>12</td>
<td>0</td>
<td>£0.00</td>
</tr>
<tr>
<td>
<a href="/circuits/edit/300/85/all_cl" class="btn btn-primary btn-circle">
<i class="fa fa-list"></i>
</a>
</td>
<td>4G</td>
<td>£30.00</td>
<td>12</td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>
<a href="/circuits/edit/307/76/all_cl" class="btn btn-primary btn-circle">
<i class="fa fa-list"></i>
</a>
</td>
<td>4G</td>
<td>£45.00</td>
<td>12</td>
<td>6</td>
<td>270.00</td>
</tr>
</tbody>
</table>

Most probably in one or more of the cells for column 9, the value there fails to convert to a number and you are getting a NaN returned by intVal function.
There are 2 issues in intVal:
line i.replace(/[\£,]/g, '')*1 can return NaN
typeof i === 'number' can be true for NaN
From what it seems, intVal is trying to check for this, but the logic is wrong.
change the intVal to:
var intVal = function ( i ) {
if(typeof i === 'string') {
i = i.replace(/[\£,]/g, '')*1;
}
// check if you got a valid number.
if (Number.isNaN(i)) {
return 0;
}
return i;
};
If the filtered total is needed, use:
total = api.column(col, {"filter": "applied"})
or
total = api.column(col, {"search": "applied"})

Related

ascending order of data from database by Id

I am trying to learn asp.net-core, and I am stuck on trying to retieve the data from database in ascending order of database Id, my code is below but not sure why its not doing it, it does acccessnding order by page but I want all the data in ascending order by database Id, any pointers wold be great...
#model IEnumerable<Citrus.Models.Customers>
#{
ViewData["Title"] = "Index";
Pager pager = new Pager();
int pageNo = 0;
if (ViewBag.Pager !=null)
{
pager = ViewBag.Pager;
pageNo = pager.CurrentPage;
}
}
<form asp-controller="Customers" asp-action="Index">
<p>
<div class="container body-content">
<div class="row">
<div class="col-lg-6">
<div class="form-group">
<label class="control-label" for="searchString"></label>
<div class="input-group">
<input class="form-control" type="text" name="searchString" placeholder="Search by company name" />
<span class="input-group-btn" name="searchString"><button class="btn btn-default btn-primary mr-1"><i class="fas fa-search"></i> Search</button></span>
#*<span asp-validation-for="searchString"></span>*#
<a class="btn btn-primary" asp-action="Create"><i class="far fa-plus-square"></i> Customer</></a>
</div>
</div>
</div>
</div>
</div>
</p>
</form>
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Company)
</th>
<th>
#Html.DisplayNameFor(model => model.Title)
</th>
<th>
#Html.DisplayNameFor(model => model.FirstName)
</th>
<th>
#Html.DisplayNameFor(model => model.Surname)
</th>
<th>
#Html.DisplayNameFor(model => model.Tel)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.OrderByDescending(i => i.Id))
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Company)
</td>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Surname)
</td>
<td>
#Html.DisplayFor(modelItem => item.Tel)
</td>
<td>
<a asp-action="Edit" asp-route-id="#item.Id"><i class="fas fa-edit"></i></a> |
<a asp-action="Details" asp-route-id="#item.Id"><i class="fas fa-info-circle"></i></a> |
<a asp-action="Delete" asp-route-id="#item.Id"><i class="fas fa-trash-alt"></i></a>
</td>
</tr>
}
</tbody>
</table>
<div class="container">
#if (pager.TotalPages > 0)
{
<ul class="pagination justify-content-end">
#if (pager.CurrentPage > 1)
{
<li class="page-item">
<a class="page-link" asp-controller="Customers" asp-action="Index" asp-route-pg="1">First</a>
</li>
<li>
<a class="page-link" asp-controller="Customers" asp-action="Index" asp-route-pg="#(pager.CurrentPage -1)">Previous</a>
</li>
}
#for (var pge = pager.StartPage; pge <= pager.EndPage; pge++)
{
<li class="page-item #(pge == pager.CurrentPage ? "active" : "")">
<a class="page-link" asp-controller="Customers" asp-action="Index" asp-route-pg="#pge"> #pge</a>
</li>
}
#if (pager.CurrentPage < pager.TotalPages)
{
<li class="page-item">
<a class="page-link" asp-controller="Customers" asp-action="Index" asp-route-pg="#(pager.CurrentPage + 1)">Next</a>
</li>
<li>
<a class="page-link" asp-controller="Customers" asp-action="Index" asp-route-pg="#(pager.TotalPages)">Last</a>
</li>
}
</ul>
}
</div>
Many Thank
John
You need to use OrderBy in backend,use OrderBy firstly,and then get the current page data,for example:
List<Citrus.Models.Customers> data = _context.Customers
.OrderBy(c => c.Id)
.Skip(position).Take(pageSize)
.ToList();
For details,you can refer to the official doc.

Secondary Ordering for Column in Datatables

As you can see from the screenshot below, I have a datatables displaying two related but disparate bits of data, Avg Score and # of Ratings:
When ordering by this column, it would be preferred if I could order by Avg Score first (numeric) and then # of Ratings second (numeric) but also keep them displayed in a single column.
I was thinking about how to modify the value of the data-order attribute to do manipulate a thing but I couldn't think of any solutions.
Anyone else solved this issue.
The data cell looks like this:
<td class="text-center sorting_1" data-search="-1" data-order="5.00">
<div class="mb-2">
<span class="badge badge-success">
5.00
</span>
</div>
<small class="text-muted">
10 ratings
</small>
</td>
You can define a custom sorting function for the column of your interest.
The snippet:
$('#example').DataTable({
"aoColumns": [{
"bSortable": true}, {"bSortable": true}, {"sType": "customAvgScoreSort", "bSortable": true}]
});
// custom sorting.......
jQuery.fn.dataTableExt.oSort["customAvgScoreSort-desc"] = function (x, y) {
return parseFloat($(y).find('span').text()) - parseFloat($(x).find('span').text()) || parseInt($(y).siblings('small').text()) - parseInt($(x).siblings('small').text());
};
jQuery.fn.dataTableExt.oSort["customAvgScoreSort-asc"] = function (x, y) {
return parseFloat($(x).find('span').text()) - parseFloat($(y).find('span').text()) || parseInt($(x).siblings('small').text()) - parseInt($(y).siblings('small').text());
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="//cdn.datatables.net/1.10.23/css/jquery.dataTables.min.css">
<script src="//cdn.datatables.net/1.10.23/js/jquery.dataTables.min.js"></script>
<table id="example" class="display" style="width:100%">
<thead>
<tr>
<th>Type</th>
<th>Unique deals</th>
<th>AVG score</th>
</tr>
</thead>
<tbody>
<tr>
<td>Sales development</td>
<td>0</td>
<td>
<div class="mb-2">
<span class="badge badge-success">
5.0
</span>
</div>
<small class="text-muted">
2 ratings
</small>
</td>
</tr>
<tr>
<td>Sales development</td>
<td>0</td>
<td>
<div class="mb-2">
<span class="badge badge-success">
5.0
</span>
</div>
<small class="text-muted">
1 ratings
</small>
</td>
</tr>
<tr>
<td>Sales development</td>
<td>0</td>
<td>
<div class="mb-2">
<span class="badge badge-success">
5.0
</span>
</div>
<small class="text-muted">
10 ratings
</small>
</td>
</tr>
<tr>
<td>Sales development</td>
<td>0</td>
<td>
<div class="mb-2">
<span class="badge badge-success">
5.0
</span>
</div>
<small class="text-muted">
3 ratings
</small>
</td>
</tr>
</tbody>
</table>

Vuejs - reading data from table

I'm trying to pull an updated value out of the table below to send it to database, but it appears that Vue does not support two-way data binding. Could anyone give me a hint on how I extract the current cell value and pass it to a function saving new data to a database?
<table v-if="tableData.length > 0" class="table table-bordered table-sm">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Date From</th>
<th scope="col">Date To</th>
<th scope="col">Days</th>
<th scope="col">Type</th>
<th scope="col">Request Date</th>
</tr>
</thead>
<tbody>
<tr v-for="(object, index) in tableData" :key="index">
<th scope="=row"><label class="tableNumberColumn">{{index + 1}}</label></th>
<td #change="readData" v-for="(value, key) in object" :key="key" v-if="key != 'formId'">
<div #change="readData" class="container tableColumnDiv" v-if="key === 'numberOfDays'" contenteditable="true">{{value}}</div>
<div class="container tableColumnDiv" v-else-if="key === 'timeOffType'" contenteditable="true">{{value}}</div>
<div v-else>
<datepicker :value="value" :bootstrap-styling="true"></datepicker>
</div>
</td>
<td>
<b-button #click="deleteRow(index)" class="btn btn-sm buttonDelete">Delete</b-button>
</td>
<td>
<b-button #click="update(index)" class="btn btn-sm buttonUpdate">Update</b-button>
</td>
<td>
<b-button class="btn btn-sm buttonPrint">Print</b-button>
</td>
</tr>
</tbody>
I am pasting the code one more time as I've removed some unnecessary stuff:
<table v-if="tableData.length > 0" class="table table-bordered table-sm">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Date From</th>
<th scope="col">Date To</th>
<th scope="col">Days</th>
<th scope="col">Type</th>
<th scope="col">Request Date</th>
</tr>
</thead>
<tbody>
<tr v-for="(object, index) in tableData" :key="index">
<th scope="=row"><label class="tableNumberColumn">{{index + 1}}</label></th>
<td v-for="(value, key) in object" :key="key" v-if="key != 'formId'">
<div class="container tableColumnDiv" v-if="key === 'numberOfDays'" contenteditable="true">{{value}}</div>
<div class="container tableColumnDiv" v-else-if="key === 'timeOffType'" contenteditable="true">{{value}}</div>
<div v-else>
<datepicker :value="value" :bootstrap-styling="true"></datepicker>
</div>
</td>
<td>
<b-button #click="deleteRow(index)" class="btn btn-sm buttonDelete">Delete</b-button>
</td>
<td>
<b-button #click="update(index)" class="btn btn-sm buttonUpdate">Update</b-button>
</td>
<td>
<b-button class="btn btn-sm buttonPrint">Print</b-button>
</td>
</tr>
</tbody>

how to keep bootstrap form button inline

When I put this button in a form it starts a new line but I want it to say inline. I tried adding class="form-inline" but it doesn't work. I must be bad at searching online because I can't find the right answer myself.
What is the bootstrap convention to keep it inline?
<div class="col-sm-12">
<table>
<thead>
<tr>
<th>Edit</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<a class="inline btn btn-info btn-xs glyphicon glyphicon-pencil"></a>
<button class="form-inline glyphicon glyphicon-trash btn btn-xs btn-danger del" type="button"></button>
</td>
</tr>
</tbody>
</table>
Fiddle
Just alter your markup a little:
Like this demo
<td>
<form class="form-inline" method="POST">
<a class="btn btn-info btn-xs glyphicon glyphicon-pencil"></a>
<button class="glyphicon glyphicon-trash btn btn-xs btn-danger del" type="button"></button>
</form>
</td>

Accordion within table rows

I am using Twitter Bootstrap. Currently I am working on Master Details looks alike table, which I am planning to place an accordion into each table's row and if it is expanded, the partial view will be reload and displayed.
Somehow it does not work as expected but if I change it to Modal, the partial view loaded perfectly.
This is the controller that process and returning the values:
public ActionResult Index(int id,int? page)
{
List<CustomerProduct> customerProducts =
(from c in RepositoryProduct.Reload(id)
select c).ToList<CustomerProduct>();
return PartialView("_CustomerProducts", customerProducts);
}
and this is the table in the view :
<table id="tbl" class="table table-condensed" style="border-collapse:collapse;">
<thead>
<tr>
<th>
#Html.ActionLink("Customer Name", "Index", new { sortOrder = ViewBag.NameSortParm, currentFilter = ViewBag.CurrentFilter })
</th>
<th>
#Html.DisplayNameFor(model => model.First().CustLocalName)
</th>
<th>
#Html.ActionLink("Country", "Index", new { sortOrder = ViewBag.CountrySortParm, currentFilter = ViewBag.CurrentFilter })
</th>
<th>
#Html.DisplayNameFor(model => model.First().City)
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr data-toggle="collapse">
<td style="display:none;">
#Html.DisplayFor(modelItem => item.CustID)
</td>
<td>
#Html.DisplayFor(modelItem => item.CustName)
</td>
<td>
#Html.DisplayFor(modelItem => item.CustLocalName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Country.CountryName)
</td>
<td>
#Html.DisplayFor(modelItem => item.City)
</td>
<td>
<a class="btn btn-small btn-info" type="button" href="#Url.Action("Index", "CustomerProduct", new { id = item.CustID })" data-toggle="collapse" data-target="##item.CustID" >Products</a>
</td>
</tr>
<tr>
<td colspan="6" class="hiddenRow">
<div id="#item.CustID" class="accordian-body collapse" tabindex="-1">
<div class="accordion-header">
<label>
<strong>#item.CustName product(s)</strong>
</label>
</div>
<div class="accordion-body">TEST</div>
</div>
</td>
</tr>
}
</tbody>
</table>
this is part of the code that calling the controller Index function :
<a class="btn btn-small btn-info" type="button" href="#Url.Action("Index", "CustomerProduct", new { id = item.CustID })" data-toggle="collapse" data-target="##item.CustID" >Products</a>
Actually I would like to load the partialview(_CustomerProduct) in the div class="accordion-body" as what I did in div class="modal-body" but no success. May I know if it is possible to do it and if yes, may I know how?
Any help will be appreciated.
for me to get the view to work i used
<td colspan="6" class="hiddenRow">
<div id="#item.CustID" class="accordian-body collapse" tabindex="-1">
<div class="accordion-header">
<label>
<strong>#item.CustName product(s)</strong>
</label>
</div>
<div class="accordion-body">
#Html.Partial("_CustomerProduct")
</div>
</div>
</td>