Passing multiple row data from JQuery Datatables into ASP.NET 5 / MVC 6 view using a submit all button - datatables

I have an ASP.NET 5 MVC application. I am using JQuery Datatables downloaded from Datatables.net for rendering my grid.
I want to be able to select multiple records on the grid and through the click of one button to be able to update the status feild on all my records. I can't figure out how to pass the information from javascript to my MVC controller through the view. Here is what I have so far.
View Code
<table class="display " id="ExpenseTable">
<thead>
<tr>
<th></th>
<th>
#Html.DisplayNameFor(model => model.ApplicationUserid)
</th>
<th>
#Html.DisplayNameFor(model => model.ExpenseDate)
</th>
... </tr>
</thead>
<tbody>
#foreach (var item in (IEnumerable<Expense>)ViewData["Expenses"])
{
<tr>
<td></td>
<td>
#Html.DisplayFor(modelItem => item.User.FullName)
</td>
<td>
#Html.DisplayFor(modelItem => item.ExpenseDate)
</td>
....
</tr>
}
</tbody>
</table>
#section Scripts {
<script>
//script is not complete
$(document).ready(function() {
var table = $('#ExpenseTable').DataTable({
dom: 'Bfrtip',
buttons: [
{
text: 'Approve All Selected Expenses',
action: function () {
}
}
],
columnDefs: [{
orderable: false,
className: 'select-checkbox',
targets: 0
} ],
select: {
style: 'multiple',
selector: 'td:first-child'
},
order: [[1, 'asc']],
} );
} );
I want to do something like this in the Controller
public IActionResult ApproveMany(IEnumerable<Expense> model)
{
foreach (var item in model)
{
item.Status = "Approved";
_context.Update(item);
_context.SaveChanges();
}
return RedirectToAction("StaffExpense"); ;
}
What I need help with is how I can take the button I have and when it is pushed take a collection of all the expense items that the user has selected on the grid, and then pass that collection into my controller so the edited changes can be pushed back to the database.

$('#updateButton').click(function ()
{
console.log("Selected rows: "+ table.rows('.selected').data().length);
var data = $.map(table.rows('.selected').data(), function (item)
{
console.log(item)
return item;
});
//Call your MVC Controller/API to do the update (pass data)
addData(data);
});
function addData(data)
{
//Add your controller name to url
/*POST*/
$.ajax({
url: '/Controller/ApproveMany',
dataType: "json",
type: "POST",
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(data),
cache: false,
success: function (result)
{
alert(result);
},
error: function (xhr)
{
alert('error');
}
})
}

This link would be helpful for you to get the desired solution
http://www.gyrocode.com/articles/jquery-datatables-checkboxes/

Related

datatable only working for the first time

function SearchUser(url, pageIndex) {
var table;
table = $('#UsersTable').DataTable({
serverSide: true,
retrieve:true,
ajax: {
url: url,
type: "POST",
data: { username: $('#Username').val(), email: $('#Email').val(), companyID: $('#LifeCompanies').val(), page: pageIndex, isLocked: $('#Locked').is(':checked') }
},
columns: [
{ "data": "UserId" },
{ "data": "Username" },
{ "data": "Email" },
{ "data": "IsLockedOut" },
{
"render": function (data, type, full, meta) {
return '<span>wahoo</span>';
}
}
]
});
}
<div id="search">
<h3>Search:</h3>
#using (Html.BeginForm("Search","Admin"))
{
<div>
<table width="500px">
<thead>
<tr>
<td>Username:</td>
<td>#Html.TextBox("Username")</td>
</tr>
<tr>
<td>Email:</td>
<td>#Html.TextBox("Email")</td>
</tr>
<tr>
<td>Locked:</td>
<td>#Html.CheckBox("Locked")</td>
</tr>
<tr>
<td colspan="2">
<div id="searchForm">
#Html.Partial("SearchBuild")
</div>
</td>
</tr>
<tr>
<td colspan="2"><input type="button" value="Search" onclick="SearchUser('/UserManagement/admin/Search',0)"/></td>
</tr>
</thead>
</table>
</div>
}
</div>
Hi the code above uses the datatables jquery plugin.
It seems to only work for the first time I use that function. The second time, it appears to hit the javascript but doesn't ever retrive any data from my mvc controller.
However if I use destroy instead of retrieve it works perfectly fine.
If I don't use retrieve or destroy, I get the "can't reinitialise table" error.
That function is just called by a button I click.
You need to modify your code to initialize your table and reload it separately.
Also it's not possible to modify initialization options via API unless you destroy and recreate the table.
You need another way to pass pageIndex variable. For example, you can create a hidden input with id PageIndex and set and retrieve value from there.
For example:
function initTable(url) {
var table;
table = $('#UsersTable').DataTable({
serverSide: true,
retrieve:true,
ajax: {
url: url,
type: "POST",
data: {
username: $('#Username').val(),
email: $('#Email').val(),
companyID: $('#LifeCompanies').val(),
page: $('#PageIndex').val(),
isLocked: $('#Locked').is(':checked')
}
},
columns: [
{ "data": "UserId" },
{ "data": "Username" },
{ "data": "Email" },
{ "data": "IsLockedOut" },
{
"render": function (data, type, full, meta) {
return '<span>wahoo</span>';
}
}
]
});
}
To search again you just need to call $('#UsersTable').DataTable().ajax.reload() API method.
If URL will change between searches use $('#UsersTable').DataTable().ajax.url(newurl).load() API method instead.

How to reload dataTables from VueJS after adding or editing?

I'd like to know how I can use this same approach when loading data from database through an api. In the first time the dataTables loads fine. However, when I add a new record, then I need to load my dataTables again with the new record. Here's my html code:
<table class="table table-striped table-bordered table-hover" id="dataTables-eventos">
<thead>
<tr class="tbheader">
<th class="text-center">#</th>
<th>Nome do Evento</th>
<th class="text-center">Editar</th>
<th class="text-center">Deletar</th>
</tr>
</thead>
<tbody>
<tr v-for="ev in eventos" :key="ev.id" track-by="id">
<td class="text-center">{{ ev.id }}</td>
<td>{{ ev.name }}</td>
<td class="text-center"><a class="cursorpointer" v-on:click="showMessage()"><span class="glyphicon glyphicon-edit"></span></a></td>
<td class="text-center"><span class="glyphicon glyphicon-trash"></span></td>
</tr>
</tbody>
</table>
And here's my VueJS code:
mounted() {
this.getEventos();
},
methods: {
getEventos() {
axios.get('/api/eventos')
.then((response) => {
this.eventos = response.data})
.then((response) => {
$('#dataTables-eventos').DataTable({
responsive: true,
"aaSorting": [[ 1, "asc" ]],
"aoColumnDefs": [
{ "bSortable" : false, "aTargets": [0,2,3] },
{ "searchable": false, "aTargets": [2,3] }
],
language: {
url: '/js/dataTables/localization/pt_BR.json'
}
});
});
},
addNewRecord() {
axios.post('/api/eventos', { nomeEvento: this.nomeEvento });
}
So after adding (or editing) a new record on my DB how can I reload my dataTables so I can see the changes?
I just ran into a situation where I needed to use vue.js with datatables.net and had to use customized table html. I created a component that allowed me to format the table as I needed using template/v-for and refresh the datatable while preserving datatables.net functionality. I hope this helps someone down the road...
export default {
data() {
return {
dataTable: null
}
},
props: {
data: Array
},
watch: {
data() {
if (this.dataTable) {
this.dataTable.destroy();
}
this.$nextTick(() => {
this.dataTable = $("#table").DataTable({
language: {
emptyTable: "No Results Found"
}
});
});
}
}
}
You can do it without reloading all the data.
Just add this.nomeEvento to array eventos after posting to server.

Datatables plugin for jQuery. How to hide rows? Export to Excel still showing hidden rows

I was able to figure out how to hide the rows I wanted using JQuery. I have a modal that pops out for the user deselects the checkbox on what rows they want to hide. It works perfectly but when I export it to excel it still displays the hidden rows. I am not using the API at all and I think that's my problem. I am hiding the rows by using .show() and .hide(). I am using the API to hide the columns and when I click my export to excel button it works just fine. Could anyone help me figure out how to hide rows and be able to export it to excel with the rows not showing on the spreadsheet?
HTML
<script type="text/javascript" language="javascript" src="https://cdn.datatables.net/buttons/1.2.4/js/dataTables.buttons.min.js">
</script>
<script type="text/javascript" language="javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jszip/2.5.0/jszip.min.js">
</script>
<script type="text/javascript" language="javascript" src="https://cdn.datatables.net/buttons/1.2.4/js/buttons.html5.min.js">
</script>
<table cellpadding="0" cellspacing="0" border="0" class="dataTable" class="example">
<thead>
<tr>
<th>Item</th>
<th>Store 1</th>
<th>Store 2</th>
<th>Store 3</th>
<th>Store 4</th>
</tr>
</thead>
<tbody>
<tr>
<td>Sugar</td>
<td>21</td>
<td>95</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>Coffee</td>
<td>5</td>
<td>41</td>
<td>5</td>
<td>1</td>
</tr>
<tr>
<td>Banana</td>
<td>123</td>
<td>323</td>
<td>22</td>
<td>233</td>
</tr>
<tr>
<td>Gum</td>
<td>13</td>
<td>213</td>
<td>2</td>
<td>33</td>
</tr>
<tr>
<td>Milk</td>
<td>23</td>
<td>24</td>
<td>44</td>
<td>242</td>
</tr>
</tbody>
</table>
</div>
</body>
JavaScript
var table = $('.example').DataTable({
dom: 'Bfrtip',
buttons: [
{
extend: 'excelHtml5',
exportOptions: {
columns: ':visible'
},
text: 'Export to Excel'
},
],
});
// I get the attribute name from the checkbox and I match it with the id on the row and when the checkbox is unchecked I hide the rows.
$('input.rowsHideSeek').click(function() {
var name = $(this).attr('name');
if ($(this).is(':checked')) {
$('#' + name).show()
} else {
$('#' + name).hide()
}
});
This is what I came up with and it seems to work. It shows and hides rows and, on export, only shows rows not hidden.
here is it is on jsbin http://jsbin.com/qituvu/edit?output
The key part is that it uses the customizeData in the extended excelHtml5.
$(document).ready(function () {
// this just creates a critera to filter on
var faketype = 1;
for (var i = 0; i < dataStore.data1.length; ++i) {
dataStore.data1[i].type = faketype++;
if (faketype == 5) faketype = 1;
}
var aTable = $('#example').DataTable({
"data": dataStore.data1,
paging:false,
"columns": [
{ "data": "name" },
{ "data": "position" },
{ "data": "office", className: "editColumn" },
{ "data": "extn" },
{ "data": "start_date" },
{ "data": "salary" },
{ "data": "type"}
], dom: 'Bfrti',
"createdRow": function( row, data, dataIndex ) {
$(row).addClass('type_' + data.type);
},
buttons: [{text:"Excel",
extend: 'excelHtml5', customizeData: function (exData) {
var rowNodes = aTable.rows().nodes();
var newData = []
for (var i = (exData.body.length - 1) ; i >= 0; i--) {
if ($(rowNodes[i]).css("display") == "none") {
continue;
}
newData[newData.length] = exData.body[i];
}
// the loop reverses order so put it back
exData.body = newData.reverse();
}}]
});
// event handler for hiding and showing rows
$("input[name='hideType']").on("click", function () {
var c = $(this).val();
var isChecked = $(this).prop('checked');
$(aTable.rows('.type_' + c).nodes()).toggle(isChecked);
aTable.rows().invalidate().draw();
});
});
The problem with jQuery hide() / show() is that you will need to tweak any part of dataTables you are using, if you want to fake persistent "hidden" rows.
Here is a few plug-in methods that provide real hide() and restore() on rows in dataTables :
$.fn.dataTableExt.hiddenRows = {};
$.fn.dataTable.Api.register( 'row.hide()', function(selector) {
var row = this.row(selector);
if (row.length == 0) return -1;
var index = row.node()._DT_RowIndex;
$.fn.dataTableExt.hiddenRows[index] = row.node().outerHTML;
row.remove().draw(false);
return index;
});
$.fn.dataTable.Api.register( 'row.restore()', function(index) {
var row = $.fn.dataTableExt.hiddenRows[index];
if (row) {
this.row.add( $(row) ).draw(false);
delete $.fn.dataTableExt.hiddenRows[index];
return true;
}
return false;
});
Now you have table.row.hide() and table.row.restore(). The methods use the dataTables API, and does nothing but maintaining a list of removed rows by their unique indexes. A demo could look like this :
var table = $('#example').DataTable({}) ;
$('#example').on('click', 'tbody tr', function() {
var index = table.row.hide(this);
var $button = $('<button></button>')
.addClass('restore')
.attr('index', index)
.text('show #'+index);
$('body').prepend($button);
})
$('body').on('click', '.restore', function() {
var index = $(this).attr('index');
table.row.restore(index);
$(this).remove();
})
When you click on a row it is hidden (i.e removed); a restore button is generated for each hidden row. If you click on the button the corresponding row is restored.
Demo -> http://jsfiddle.net/s183ek2q/

paging using knockout js

At first I have displlay data using knockout js successful,here is my code:
Js
var viewMode = {
lookupCollection: ko.observableArray()
};
$(document).ready(function () {
$.ajax({
type: "GET",
url: "/Home/GetIndex",
}).done(function (data) {
$(data).each(function (index, element) {
viewModel.lookupCollection.push(element);
});
ko.applyBindings(viewMode);
}).error(function (ex) {
alert("Error");
});
});
View:
<table class="paginated">
<tr>
<th>
Name
</th>
<th>
Price
</th>
<th>
Category
</th>
<th></th>
</tr>
<tbody data-bind="foreach: lookupCollection">
<tr>
<td data-bind="text: Name"></td>
<td data-bind="text: price"></td>
<td data-bind="text: Category"></td>
<td>
<button class="btn btn-success">Edit</button>
<button class="btn btn-danger">Delete</button>
</td>
</tr>
</tbody>
</table>
However, I need more code to paging the list items, I follow this site http://knockoutjs.com/examples/grid.html and replay my code but It has not display my list items:
JS:
var initialData = {
lookupCollection: ko.observableArray()
};
var PagedGridModel = function (items) {
this.items = ko.observableArray(items);
this.sortByName = function () {
this.items.sort(function (a, b) {
return a.name < b.name ? -1 : 1;
});
};
this.jumpToFirstPage = function () {
this.gridViewModel.currentPageIndex(0);
};
this.gridViewModel = new ko.simpleGrid.viewModel({
data: this.items,
columns: [
{ headerText: "Name", rowText: "Name" },
{ headerText: "Category", rowText: "Category" },
{ headerText: "Price", rowText: function (item) { return "$" + item.price.toFixed(2) } }
],
pageSize: 4
});
};
$(document).ready(function () {
$.ajax({
type: "GET",
url: "/Home/GetIndex",
}).done(function (data) {
$(data).each(function (index, element) {
viewModel.lookupCollection.push(element);
});
ko.applyBindings(new PagedGridModel(initialData));
}).error(function (ex) {
alert("Error");
});
});
View:
<div data-bind='simpleGrid: gridViewModel'> </div>
<button data-bind='click: sortByName'>
Sort by name
</button>
<button data-bind='click: jumpToFirstPage, enable: gridViewModel.currentPageIndex'>
Jump to first page
</button>
thankyou very much your answer:
The "simpleGrid" binding u try to use is a custom one, not available by default in knockout.
Here's a simple example for pagination using a computed observable :
Fiddle : http://jsfiddle.net/RapTorS/qLHwx/
var viewModel = function () {
var self = this;
self.pageSize = 4;
self.currentPage = ko.observable(1);
self.lookupCollection = ko.observableArray([]);
self.currentCollection = ko.computed(function () {
var startIndex = self.pageSize * (self.currentPage() - 1);
var endIndex = startIndex + self.pageSize;
return self.lookupCollection().slice(startIndex, endIndex);
});
};

How can we change width of search fields in DataTables

Can I change the width of search text fields in dataTables ?
I am writing following code right now but it is not working.
$('#example').dataTable()
.columnFilter({ sPlaceHolder: "head:before",
aoColumns: [ { type: "text",width:"10px" },
{ type: "date-range" },
{ type: "date-range" }
]
});
And if my dataTables is dynamically generated like as gven below:
$('#example').dataTable({
"aaData": aDataSet,
"aoColumns": [
{ "sTitle": "#","sWidth": "10px" },
{ "sTitle": "ID" },
{ "sTitle": "Staff Name" },
{ "sTitle": "Rig Days" },
{ "sTitle": "Manager"},
{ "sTitle": "Grade"},
{ "sTitle": "Tools"},
{ "sTitle": "Vacations"},
{ "sTitle": "Presently On"},
]
});
}
How to add Search field in this dynamically created DataTable to search by each column?
None of the above solution worked for me; then I got this:
$(document).ready(function () {
$('.dataTables_filter input[type="search"]').css(
{'width':'350px','display':'inline-block'}
);
});
And it worked perfectly!
If you want to place a placeholder too inside the search box use this ..
$('.dataTables_filter input[type="search"]').
attr('placeholder','Search in this blog ....').
css({'width':'350px','display':'inline-block'});
And this will work for sure.
To change the search box width, all I had to do was go into my .css file and enter the following:
.dataTables_filter input { width: 300px }
it's worked for me
<script>
var datatable = $('#table').DataTable({
...<datatables properties>,
initComplete: function () {
$('.dataTables_filter input[type="search"]').css({ 'width': '350px', 'display': 'inline-block' });
}
</script>
The only thing worked for me is this css.
$(document).ready(function(){
$('#datatable-buttons_filter').css({"position":"relative","left":"-100px"});
});
try to use css to change the width
example
.text_filter{
width:45%;
min-width:200px;
}
I applied this solution in my environment (Laravel 5.2, yajra/Laravel-DataTables 6.0, Bootstrap 3.x):
My table:
<table id="my-table" class="table table-striped table-hover" style="font-size: 80%">
<thead>
<tr>
<th class="input-filter" style="text-align:center;width: 5%">ID</th>
...
</tr>
</thead>
<tbody></tbody>
<tfoot>
<tr>
<th style="text-align:center;width: 5%">ID</th>
...
</tr>
</tfoot>
My script:
<script type="text/javascript">
var dt = $('#my-table').DataTable({
stateSave: true,
responsive: true,
processing: true,
serverSide: true,
order: [[ 0, "desc" ]],
lengthMenu: [[5, 10, -1], [5, 10, "All"]],
ajax: {
url: '...',
},
columns: [
{data: 'id', name: 'id',orderable:true,searchable:true},
...
],
language: {
url: '....'
},
initComplete: function () {
this.api().columns('.input-filter').every(function () {
var column = this;
var input = document.createElement("input");
// start - this is the code inserted by me
$(input).attr( 'style', 'text-align: center;width: 100%');
// end - this is the code inserted by me
$(input).appendTo($(column.footer()).empty())
.on('keyup', function () {
var val = $.fn.dataTable.util.escapeRegex($(this).val());
column.search(val ? val : '', true, true).draw();
});
});
}
});
</script>
here is the repeater
<asp:Repeater ID="rptClients" runat="server">
<HeaderTemplate>
<table id="example" class="display">
<thead>
<tr style="color:#fff;">
<th>Edit</th>
<th>Client Name</th>
<th>Address</th>
<th>City</th>
<th>State</th>
<th>Zip</th>
<th>Phone</th>
<th>Fax</th>
<th>Client Type</th>
<th>Active</th>
</tr>
<tr id="filterRow">
<td>Edit</td>
<td>Client Name</td>
<td>Address</td>
<td>City</td>
<td>State</td>
<td>Zip</td>
<td>Phone</td>
<td>Fax</td>
<td>Client Type</td>
<td>Active</td>
</tr>
</thead>
<tfoot style="display:none;">
<tr>
<td> </td>
</tr>
</tfoot>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><div class="padBtm-05 padTop-10"><asp:Button runat="server" ID="btnEdit" Text="Edit" /></div></td>
<td>
<%# Container.DataItem("ClientName")%>
</td>
<td>
<%# Container.DataItem("ClientAddress")%>
</td>
<td>
<%# Container.DataItem("ClientCity")%>
</td>
<td>
<%# Container.DataItem("State")%>
</td>
<td>
<%# Container.DataItem("ClientZip")%>
</td>
<td>
<%# Container.DataItem("ClientPhone")%>
</td>
<td>
<%# Container.DataItem("ClientFax")%>
</td>
<td>
<%# Container.DataItem("ClientType")%>
</td>
<td>
<%# Container.DataItem("Active")%>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
There are filters on all columns. Here I actually hide the edit column filter since it doesn't need one. If i don't render a filter for this column my filtering is off 1 column. In the javascript i target my table row which will end up being my title placeholder. Based on the placeholder name you can run an if statement that allows you to target the input element and set the width of the item. I have found setting the width of the filter sets the column width on the table.
// apply the input styling
$('#example thead td').each(function (i) {
var title = $('#example thead th').eq($(this).index()).text();
if (title == "Edit") {
var serach = '<input type="text" style="display:none;" placeholder="' + title + '" />';
} else if (title == "Client Name") {
var serach = '<input type="text" style="width:370px;" placeholder="' + title + '" />';
} else if (title == "Zip") {
var serach = '<input type="text" style="width:50px;" placeholder="' + title + '" />';
} else {
var serach = '<input type="text" placeholder="' + title + '" />';
}
$(this).html('');
$(serach).appendTo(this).keyup(function () { table.fnFilter($(this).val(), i) })
});
// Apply the search
table.columns().every(function () {
var that = this;
$('input', this.footer()).on('keyup change', function () {
if (that.search() !== this.value) {
that
.search(this.value)
.draw();
}
});
});
I have used the below code while using dataTables
JS
$('#du_ft_table').dataTable( { <br/>
"bProcessing": true,<br/>
"bServerSide": true,<br/>
scrollX: true,<br/>
"sAjaxSource": "../server_processing_man.php?sourceC=du_ft&rights=1&mandatory=1&retailer_id=2725",
"aoColumns": [
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
{ "mData": function(obj) {
return '<a class="btn btn-xs btn-primary" href="EBSNL_NW='+obj[0]+'" alt="Edit" title="Edit"><i class="fa fa-pencil-square-o"></i></a>';
}}
]
} );
$('.dataTables_scrollFootInner tfoot th').each( function () {<br/>
var title = $(this).text();<br/>
if(title != '') $(this).html( '<input type="text" placeholder="Search '+title+'" />' );<br/>
});
var duft_table = $('#du_ft_table').DataTable();
// Apply the search
duft_table.columns().every( function () {<br/>
var that = this;<br/>
$( 'input', this.footer() ).on( 'keyup change', function () {<br/>
if ( that.search() !== this.value ) {<br/>
that.search(this.value).draw();<br/>
}<br/>
} );
});
Nativ javascript solution.
$(document).ready(function() {
$('#yourTableId').DataTable();
var addressTableFilter = document.getElementById('addressTable_filter');
addressTableFilter.firstChild.getElementsByTagName('input')[0].style.width = "400px";
addressTableFilter.firstChild.getElementsByTagName('input')[0].setAttribute('placeholder', 'Search');
addressTableFilter.firstChild.removeChild(document.getElementById('addressTable_filter').firstChild.firstChild);
});
Dont forget to wrap everything inside document ready(if u using it)otherwise other lines may kick in before datatable is initiated and you will get error.
This will also remove search label and add it as placeholder inside input box.