Reputation: 29
I have question about how to bind data from controller. This is the idea: I have list of data in datatable. I need to delete 1 data from datatable. I'm using ajax post to call actionresult in controller and send the model. And my controller will delete the data, and return the model to view.
Here is my viewmodels:
public class SampleHeaderViewModels
{
[Display(Name = "ID")]
public int intID { get; set; }
[Display(Name = "Field 1")]
public string txtField1 { get; set; }
[Display(Name = "Field 2")]
public string txtField2 { get; set; }
}
public class SampleDetailViewModels
{
[Display(Name = "ID")]
public int intID { get; set; }
[Display(Name = "Line")]
public int intLine { get; set; }
[Display(Name = "Detail 1")]
public string txtDetail1 { get; set; }
[Display(Name = "Detail 2")]
public string txtDetail2 { get; set; }
}
public class SampleViewModels
{
public SampleHeaderViewModels Header { get; set; }
public List<SampleDetailViewModels> Detail { get; set; }
public SampleViewModels()
{
Header = new SampleHeaderViewModels();
Detail = new List<SampleDetailViewModels>();
}
}
And this is my View:
<div class="row">
<div class="block">
<div class="block-content controls">
<div class="col-md-6">
<div class="row-form">
<div class="col-md-4">
@Html.LabelFor(m => m.Header.txtField1, htmlAttributes: new { @class = "control-label" })
</div>
<div class="col-md-8">
@Html.HiddenFor(m => m.Header.intID)
@Html.TextBoxFor(m => m.Header.txtField1, htmlAttributes: new { @class = "form-control" })
</div>
</div>
<div class="row-form">
<div class="col-md-4">
@Html.LabelFor(m => m.Header.txtField2, htmlAttributes: new { @class = "control-label" })
</div>
<div class="col-md-8">
@Html.TextBoxFor(m => m.Header.txtField2, htmlAttributes: new { @class = "form-control" })
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="block">
<div class="block-content controls">
<div class="col-md-12">
<div class="row-form">
<table id="tbDataTable" class="table table-bordered">
<thead>
<tr>
<td>
</td>
<td>
@Html.LabelFor(m => m.Detail.FirstOrDefault().intLine)
</td>
<td>
@Html.LabelFor(m => m.Detail.FirstOrDefault().txtDetail1)
</td>
<td>
@Html.LabelFor(m => m.Detail.FirstOrDefault().txtDetail2)
</td>
</tr>
</thead>
<tbody>
@if (Model.Detail != null)
{
for (int x = 0; x <= Model.Detail.Count - 1; x++)
{
<tr>
<td>
<button type="button" class="btn btn-primary" onclick="return DeleteDetail('@Model.Detail[x].intLine');">Delete</button>
</td>
<td>
@Html.DisplayFor(m => @Model.Detail[x].intLine)
@Html.HiddenFor(m => @Model.Detail[x].intLine)
</td>
<td>
@Html.DisplayFor(m => @Model.Detail[x].txtDetail1)
@Html.HiddenFor(m => @Model.Detail[x].txtDetail1)
</td>
<td>
@Html.DisplayFor(m => @Model.Detail[x].txtDetail2)
@Html.HiddenFor(m => @Model.Detail[x].txtDetail2)
</td>
</tr>
}
}
</table>
</div>
<div class="row-form">
<div class="col-md-2">
<button type="button" id="btnAddDetail" class="btn btn-info">Add Detail</button>
</div>
</div>
</div>
</div>
</div>
</div>
This is my Javascript:
function DeleteDetail(intLine)
{
debugger;
var modelHeader = {
"intID": $('#@Html.IdFor(m => m.Header.intID)').val(),
"txtField1": $('#@Html.IdFor(m => m.Header.txtField1)').val(),
"txtField2": $('#@Html.IdFor(m => m.Header.txtField2)').val(),
};
var modelDetail = @Html.Raw(JsonConvert.SerializeObject(Model.Detail));
$.ajax({
url: '/Sample/DeleteDetail',
type: 'POST',
datatype: 'JSON',
contentType: 'application/json',
data: JSON.stringify(
{
objHeader : modelHeader,
objDetail : modelDetail,
intLine : intLine
}),
cache: false,
success: function (data) {
@*window.location.replace('@Url.Action("Detail")');*@
},
error: function (data) {
console.log(data);
}
});
}
And this is my controller:
[HttpPost]
public ActionResult DeleteDetail(SampleHeaderViewModels objHeader, List<SampleDetailViewModels> objDetail, int intLine)
{
objDetail.Remove(objDetail.Where(m => m.intLine == intLine).FirstOrDefault());
SampleViewModels obj = new SampleViewModels();
obj.Header = objHeader;
obj.Detail = objDetail;
TempData["model"] = obj;
return View("Index", obj);
}
The question is: In my code, when I pressed "Delete" button in datatable, it will call function AJAX POST DeleteDetail in javascript. And it will send the Header model and Detail model to my Controller. And my controller will remove the selected row and return the model to View. And my View get the latest model. Which is 1 row already deleted. But it will not render the datatable. So the deleted data is still there. I'm trying using @url to post the page when the AJAX succeded, but still no luck. How to force the datatable to bind the latest model?
Thanks.
Edited:
I'm trying to refresh the data without refresh the page. Just refresh the datatable.
Here is my Controller:
public ActionResult DeleteDetail(SampleHeaderViewModels objHeader, List<SampleDetailViewModels> objDetail, int intLine)
{
objDetail.Remove(objDetail.Where(m => m.intLine == intLine).FirstOrDefault());
SampleViewModels obj = new SampleViewModels();
obj.Header = objHeader;
obj.Detail = objDetail;
TempData["model"] = obj;
var json = JsonConvert.SerializeObject( new {detail = obj.Detail});
return Content(json, "application/json");
}
And this is my Javascript:
function DeleteDetail(intLine)
{
debugger;
var modelHeader = {
"intID": $('#@Html.IdFor(m => m.Header.intID)').val(),
"txtField1": $('#@Html.IdFor(m => m.Header.txtField1)').val(),
"txtField2": $('#@Html.IdFor(m => m.Header.txtField2)').val(),
};
var modelDetail = @Html.Raw(JsonConvert.SerializeObject(Model.Detail));
$.ajax({
url: '/Sample/DeleteDetail',
type: 'POST',
datatype: 'JSON',
contentType: 'application/json',
data: JSON.stringify(
{
objHeader : modelHeader,
objDetail : modelDetail,
intLine : intLine
}),
cache: false,
success: function (data) {
debugger;
table = $("#tbDataTable").dataTable();
oSettings = table.fnSettings();
table.fnClearTable(this);
for (var i=0; i < data.detail.length; i++)
{
table.oApi._fnAddData(oSettings, data.detail[i]);
//this part always send error DataTables warning: table id=tbDataTable - Requested unknown parameter '0' for row 0.
}
oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
table.fnDraw();
},
error: function (data) {
console.log(data);
}
});
}
But it send me an error DataTables warning: table id=tbDataTable - Requested unknown parameter '0' for row 0. The view and view model is still same like the first question. Please help me.
Upvotes: 1
Views: 11441
Reputation: 27
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.10.16/js/dataTables.bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/4.4.0/bootbox.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/sweetalert.min.js"></script>
Controller: public JsonResult GetProductsData(){ var alldata = dbobj.products.ToList();
var result = from x in alldata
select new[]
{
Convert.ToString(x.pid),
Convert.ToString(x.pname),
Convert.ToString(x.pprice)
};
return Json(new
{
aaData = result
},
JsonRequestBehavior.AllowGet);
}
public JsonResult deleteRecord(int ID)
{
try
{
var data = dbobj.products.Where(x => x.pid == ID).FirstOrDefault();
dbobj.products.Remove(data);
dbobj.SaveChanges();
return Json(1, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
return Json(0, JsonRequestBehavior.AllowGet);
}
}
}
Upvotes: 0
Reputation: 27
Jquery:
<script>
var Display;
$(document).ready(function () {
$('#ProductTable').DataTable();
Display = function () {
var URL = '@Url.Action("GetProductsData", "Product")';
oTable = $('#ProductTable').DataTable({
dom: 'Bfrtip',
"bPaginate": false,
buttons: [
'excel', 'pdf', 'print'
],
"processing": false,
"serverSide": false,
"bSort": false,
"searching": true,
"sAjaxSource": URL,
"pageLength": 10,
"bDestroy": true,
"bLengthChange": true,
"scrollX": true,
"scrollY": ($(window).height() - 200),
"pagingType": "full_numbers",
"sEmptyTable": "Loading data from server",
"fnServerData": function (sSource, aoData, fnCallback) {
$.ajax({
"dataType": 'json',
"type": "POST",
"url": sSource,
"data": aoData,
"success": fnCallback
});
},
"columns": [
{
"sWidth": "5%",
"bSortable": true,
"sClass": "TextCenter ID",
"visible": false,
"render": function (data, type, row, meta) {
return (row[0])
}
},
{
"sWidth": "5%",
"sClass": "rightalign ",
"render": function (data, type, row, meta) {
return (row[1])
}
},
{
"sWidth": "10%",
"sClass": "rightalign TA_C",
"render": function (data, type, row, meta) {
return (row[2])
}
},
{
"swidth": "5%",
"sclass": "TextCenter Action",
"render": function (data, type, row, meta) {
return '<button class="btn btn-primary fa fa-check-square" title="Edit" onclick="editdata(' + row[0] + ',\'' + row[1] + '\',' + row[2] + ')"></button>' +
'<button class="btn btn-danger glyphicon glyphicon-trash" title="Delete" onclick="deletedata(' + row[0] + ')" style="margin-left: 10px;"></button>';
}
}
], "fnInitComplete": function (oSetting, json) {
}
});
}
Display();
$("#btninsert").click(function () {
var fdata = new FormData();
fdata.append("id","0");
fdata.append("pname",$("#txtpname").val());
fdata.append("pprice", $("#txtpprice").val());
$.ajax({
url: '@Url.Action("InupProduct", "Product")',
type: "POST",
contentType: false, // Not to set any content header
processData: false, // Not to process data
data: fdata,
success: function (result) {
if (result == 1) {
swal("Successfully Product Inserted!", "", "success", {
button: "Close",
});
clear();
Display();
}
else {
swal("Product Not Inserted!", "", "error", {
button: "Close",
});
}
},
error: function (err) {
alert(err.statusText);
}
});
});
$("#btnupdate").click(function () {
var fdata = new FormData();
fdata.append("id", $("#hdnID").val());
fdata.append("pname", $("#txtuppname").val());
fdata.append("pprice", $("#txtuppprice").val());
$.ajax({
url: '@Url.Action("InupProduct", "Product")',
type: "POST",
contentType: false, // Not to set any content header
processData: false, // Not to process data
data: fdata,
success: function (result) {
if (result == 1) {
swal("Successfully Product Updated!", "", "success", {
button: "Close",
});
clear();
Display();
$('#mmd').modal('hide');
}
else {
swal("Product Not Updated!", "", "error", {
button: "Close",
});
}
},
error: function (err) {
alert(err.statusText);
}
});
});
function clear() {
$("#txtpname").val("");
$("#txtpprice").val("");
}
});
function deletedata(ID) {
bootbox.confirm({
title: "Please Confirm",
message: "Are you sure to delete this record.",
buttons: {
cancel: {
label: '<i class="fa fa-times"></i> Cancel'
},
confirm: {
label: '<i class="fa fa-check"></i> Confirm'
}
},
callback: function (result) {
if (result == true) {
var data = { "ID": ID };
$.ajax({
url: '@Url.Action("deleteRecord", "Product")',
type: "POST",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(data),
dataType: "json",
success: function (response) {
if (response == 1) {
swal("Successfully Product Deleted!", "", "success", {
button: "Close",
});
Display();
}
else {
swal("Product Not Deleted!", "", "error", {
button: "Close",
});
}
}
});
}
}
});
}
function editdata(pid,pname,price)
{
$("#hdnID").val(pid);
$("#txtuppprice").val(price);
$("#txtuppname").val(pname);
$('#mmd').modal();
}
</script>
<style>
.dataTables_scrollBody{
position: relative;
overflow: auto;
margin-top: -5%;
width: 100%;
height: 502px;
}
</style>
Upvotes: 0
Reputation: 1021
Action Method return true if you successfully deleted a record from database other wise return false:
public ActionResult DeleteDetail(SampleHeaderViewModels objHeader,
List<SampleDetailViewModels> objDetail, int intLine)
{
...
...
db.SaveChanges();
return Json(new { Success = true; });
}
Reload the current page in success method of ajax ,
success: function (data) {
if(data.Success) {
// reload you page through javacript/jquery
window.location.reload();
//location.reload(true);
}
Upvotes: 1