i Have a table with orders,
i want to create a button per each line in the table that when clicked, will change the value of a field in that record (order status to cancelled) without redirect to any update page.
i created a link using HtmlAction but its not activating the function(see screen shot)
Here is the actionLink:
<td>
<div class="text-center">
<p>#Html.ActionLink("cancel", "CancelOrder", "Order",new { id = #order.Id })</p>
</div>
</td>
Thank you!
You get a 405 error because the "CancelOrder" method should be a get request instead of a post request.
Below is a work demo:
Index View:
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.IsCancle)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var order in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => order.Name)
</td>
<td>
#Html.DisplayFor(modelItem => order.IsCancle)
</td>
<td>
<p>#Html.ActionLink("cancel", "CancelOrder", "Orders", new { id = #order.Id })</p>
</td>
</tr>
}
</tbody>
</table>
Controller:
public async Task<IActionResult> Index()
{
return View(await _context.Orders.ToListAsync());
}
[HttpGet]
public IActionResult CancelOrder(int id)
{
var order = _context.Orders.Find(id);
order.IsCancle = true;
_context.Update(order);
_context.SaveChanges();
return RedirectToAction(nameof(Index));
}
Result:
By the way,if you don't want to refresh the entire page, I recommend you to use Ajax. Here is an example of using Ajax for partial refresh:
Index View:
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var order in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => order.Name)
</td>
<td>
<button id="Cancle">Cancle</button>
<input type="hidden" name="Id" value="#order.Id" />
</td>
</tr>
}
</tbody>
</table>
#section Scripts
{
<script>
$('#Cancle').on('click', function (e) {
var id = $('input[name=Id ]').val();
$.ajax({
url: 'Orders/CancelOrder',
type: 'post',
data: { "id": id } ,
dataType: 'json',
success: function (data) {
console.log(data)
}
})
});
</script>
}
Controller:
public async Task<IActionResult> Index()
{
return View(await _context.Orders.ToListAsync());
}
[HttpPost]
public IActionResult CancelOrder(int id)
{
var order = _context.Orders.Find(id);
order.IsCancle = true;
_context.Update(order);
_context.SaveChanges();
return Json(id);
}
Result:
I have created a controller with ActionResult Index and created a list of Student class as:
public ActionResult Index()
{
var list = new List<Student>()
{
new Student{Id=1,RegNo="Bcs153048",Name="Ali",Age=21,},
new Student{Id=2,RegNo="Bcs153044",Name="Talha",Age=22,},
new Student{Id=3,RegNo="Bcs153064",Name="Luqman",Age=20,},
new Student{Id=4,RegNo="Bcs153054",Name="Saad",Age=19,},
new Student{Id=5,RegNo="Bcs153036",Name="Hashir",Age=20,},
};
//var jsonString = JsonConvert.SerializeObject(list);
//return View(list);
return Json(list , JsonRequestBehavior.AllowGet);
}
I the view i want to view the list of students in JQuery datatable and i did something like this:
<table id="students" class="table table-bordered table-hover">
<thead>
<tr>
<th>Id</th>
<th>Registeration No</th>
<th>Name</th>
<th>Age</th>
</tr>
</thead>
<tbody></tbody>
and then below this i have written script as
#section scripts
{
<script>
$(document).ready( function () {
var dataTable = $("#students").DataTable({
ajax: {
url: "/student/index",
dataSrc: "",
},
columns: [
{
data: "Id"
},
{
data: "RegNo",
},
{
data: "Name"
},
{
data: "Age",
}
]
});
});
</script>
}
But i got the Json result when i run the application and navigate to /Student/index wile i want to display list in Jquery datatable :
[{"Id":1,"Name":"Ali","Age":21,"RegNo":"Bcs153048"},{"Id":2,"Name":"Talha","Age":22,"RegNo":"Bcs153044"},{"Id":3,"Name":"Luqman","Age":20,"RegNo":"Bcs153064"},{"Id":4,"Name":"Saad","Age":19,"RegNo":"Bcs153054"},{"Id":5,"Name":"Hashir","Age":20,"RegNo":"Bcs153036"}]
I have added libraries in Bundle.config as:
Libraries in BundleConfig
Add a partial view and add the below script and html table. call that partial view in your main view.
<script>
$(document).ready(function () {
//Call student Details jsonResult Method
$.getJSON("/student/index",
function (json) {
var tr;
//Append each row to html table
for (var i = 0; i < json.length; i++) {
tr = $('<tr/>');
tr.append("<td>" + json[i].Id + "</td>");
tr.append("<td>" + json[i].Name + "</td>");
$('table').append(tr);
}
});
});
<table class="table table-bordered table-condensed table-hover table-striped">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>City</th>
<th>Address</th>
</tr>
</thead>
<tbody></tbody>
call the partialview
<div style="margin-top:20px">#Html.Partial("studentDetails");</div>
You said
"i get the Json result when i run the application and navigate to
/Student/index "
...yes, that's correct, because that's what "student/index" returns in your code. But why are you navigating there in your browser directly? It doesn't lead to a view which you can display to the user. It's the ajax call (defined in the DataTables setup) which should request that data. I think maybe you have become confused between the two things.
In your browser you should be navigating to the View which renders the datatable. This will have a separate action method which returns a whole HTML view, not JSON, and thus also has a separate URL from the method which fetches the JSON.
So when you make a HTTP request to the main view in your browser, it loads the view HTML into the browser. Then the JS code on that page runs, loads the DataTable, which triggers the separate HTTP request via ajax to fetch the JSON data.
For example:
"Student" controller:
//load the view
[HttpGet]
public ActionResult Index()
{
return View();
}
//load the JSON
[HttpGet]
public JsonResult GetStudentList()
{
var list = new List<Student>()
{
new Student{Id=1,RegNo="Bcs153048",Name="Ali",Age=21,},
new Student{Id=2,RegNo="Bcs153044",Name="Talha",Age=22,},
new Student{Id=3,RegNo="Bcs153064",Name="Luqman",Age=20,},
new Student{Id=4,RegNo="Bcs153054",Name="Saad",Age=19,},
new Student{Id=5,RegNo="Bcs153036",Name="Hashir",Age=20,},
};
return Json(list , JsonRequestBehavior.AllowGet);
}
"Student/Index" View:
<table id="students" class="table table-bordered table-hover">
<thead>
<tr>
<th>Id</th>
<th>Registration No</th>
<th>Name</th>
<th>Age</th>
</tr>
</thead>
<tbody></tbody>
</table>
#section scripts
{
<script>
$(document).ready( function () {
var dataTable = $("#students").DataTable({
ajax: {
url: '#Url.Action("GetStudentList", "student")', //note the use of a HTML helper to generate the correctly routed URL, and also the change of action name to "GetStudentList"
dataSrc: "",
},
columns: [
{
data: "Id"
},
{
data: "RegNo",
},
{
data: "Name"
},
{
data: "Age",
}
]
});
});
</script>
}
I am trying to bind a table using a foreach binding of Knockout. However, my observable properties are reflecting changes, but the data is not able to bind with the table. Below is the code:
HTML
<div class="container-fluid ">
<table class="table table-Alternate table-condensed header" id="appTable">
<thead>
<tr>
<th></th>
<th style="font-weight: bold;">Market </th>
<th style="font-weight: bold;">Product Name</th>
<th style="font-weight: bold;">Company Name</th>
<th style="font-weight: bold;">Product Id</th>
<th style="font-weight: bold;">Publisher Name </th>
<%--<th><span style="font-weight: bold;" id="Span1">Action</span></th>--%>
</tr>
</thead>
<tbody id="appAnnieData" data-bind="foreach: CompanyInfo">
<%-- <tr>
<td><span data-bind="text:Market"></span></td>
<td><span data-bind="text: Product_Name"></span></td>
<td><span data-bind="text: Company_Name"></span></td>
<td><span data-bind="text: Product_id"></span></td>
<td><span data-bind="text: Unified_Product_Name"></span></td>
</tr>--%>
</tbody>
</table>
</div>
script
$(document).on('click', '#appAnnieSearch', function() {
mainModel = $(this);
var id = $(this).parents().find("#txtCompanyId").val();
if (id == "") {
toastr.info('Please enter Company ID');
return false;
}
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
url: "../../Services/AService.asmx/GetCompanyInformation",
data: {
id: JSON.stringify(id)
},
contentType: "application/json; charset=utf-8",
dataType: "json",
async: true,
success: function(res) {
if (res.d != null && res.d != undefined && res.d != "NotFound") {
var options = JSON.parse(res.d);
FillDetailsForCompany(options.app_list);
} else {
toastr.options.timeOut = 7000;
toastr.options.closeButton = true;
toastr.info('No information found for the selected Company Id. Please try another one.');
}
document.getElementById("loader_search").style.display = "none";
},
error: function(errormsg) {
$(".dropdown_SubDomainLoading").hide();
toastr.options.timeOut = 7000;
toastr.options.closeButton = true;
toastr.error('Something Went Wrong');
}
});
});
function FillForCompany(appanydata) {
var dataArray = [];
for (var i = 0; i < appanydata.length; i++) {
dataArray.push(new AppViewModel(appanydata[i].market, appanydata[i].product_name, appanydata[i].company_name, appanydata[i].product_id, appanydata[i].unified_product_name,
appanydata[i].product_franchise_id, appanydata[i].product_category, appanydata[i].unpublished, appanydata[i].company_id, appanydata[i].unified_product_id, appanydata[i].product_franchise_name, appanydata[i].publisher_id,
appanydata[i].publisher_name, appanydata[i].product_code));
}
DomainModule.dataContext.CompanyInfo(dataArray);
}
function AppViewModel(market, product_name, company_name, product_id, unified_product_name, product_franchise_id, product_category, unpublished, company_id,
unified_product_id, product_franchise_name, publisher_id, publisher_name, product_code) {
self = this;
self.Market = ko.observable(market);
self.Product_Name = ko.observable(product_name);
self.Company_Name = ko.observable(company_name);
self.Product_Id = ko.observable(product_id);
self.Unified_Product_Name = ko.observable(unified_product_name);
self.Product_Franchise_Id = ko.observable(product_franchise_id);
self.Product_Category = ko.observable(product_category);
self.Unpublished = ko.observable(unpublished);
self.Company_Id = ko.observable(company_id);
self.Unified_Product_Id = ko.observable(unified_product_id);
self.Product_Franchise_Name = ko.observable(product_franchise_name);
self.Publisher_Id = ko.observable(publisher_id);
self.Publisher_Name = ko.observable(publisher_name);
self.Product_Code = ko.observable(product_code);
}
The observable property is getting populated and when I inspect the object value DomainModule.dataContext.CompanyInfo has the respective data. However, I do not get the table populated.
I am trying to fetch the data on the click event of a button. Is there something I am missing?
**This is ajax function**
$.ajax({
type : "Get",
url : url,
data:$("#client").serialize(),
dataType:'json',
success : function(response)
{
},
error : function(e)
{
alert('Error: ' + e);
}
});
This is my Controller
#RequestMapping(value = "/authenticate/ajaxObj", method = RequestMethod.GET)
public #ResponseBody ArrayList<String> ajax_Claims(Model model,
#ModelAttribute("CalculatorDO") CalculatorDO calculatorDO)
{
System.out.println("\nAjax Hit the Controller");
ArrayList<String> clist=new ArrayList<>();
ArrayList<String> namelist=new ArrayList<>();
ArrayList<String> classlist=new ArrayList<>();
ArrayList<String> address=new ArrayList<>();
namelist=calculatorDO.getNameList();
classlist=calculatorDO.getNameList();
address=calculatorDO.getNameList();
clist.add(namelist);
clist.add(classlist);
clist.add(address);
model.addAttribute("nameList", clist);
return clist;
}
My table
<table>
<thead>
<tr>
<th>Name</th>
<th>Class</th>
<th>address</th>
</tr>
</thead>
<tbody>
<c:forEach items="${nameList}" var="list">
<tr>
<td><c:out value="${list.namelist}"/></td>
<td><c:out value="${list.classlist}" /></td>
<td><c:out value="${list.address}"/></td>
</tr>
</c:forEach>
</tbody>
</table>
I want to reload the table.
Replace <tbody> with
<tbody id="ajax-tbody-results">
</tbody>
And use jQuery tmpl to fill the table with your data (jQuery tmpl )
<script id="table-template" type="text/x-jquery-tmpl">
<tr>
<td>${namelist}</td>
<td>${classlist}</td>
</tr>
</script>
$.ajax({
type : "Get",
url : url,
dataType:'json',
success : function(response)
{
jQuery("#table-template").tmpl(data).appendTo("#ajax-tbody-results");
},
error : function(e)
{
alert('Error: ' + e);
}
});
I'm having problem with binding JSON from ASP.net webform webapi to the viewmodel with KnockoutJs. There is no problem with wepapi and mapping to mappedQuickEntries.
Where did I get it wrong? Thanks.
Error:
Error: Unable to parse bindings.
Message: ReferenceError: ItemPartNumb is not defined;
Bindings value: value: ItemPartNumb
View:
<div>
<table border="1" cellpadding="0" cellspacing="0">
<tbody data-bind="foreach: quickEntries">
<tr>
<td data-bind="value: ItemPartNumb"></td>
<td data-bind="value: ItemDescription"></td>
</tr>
</tbody>
</table>
ViewModel:
<script type="text/javascript">
var QuickEntry = function(_itemPartNumb, _itemDescription) {
this.ItemPartNumber = ko.observable(_itemPartNumb);
this.ItemDescription = ko.observable(_itemDescription);
};
function QuickEntriesViewModel () {
var self = this;
self.quickEntries = ko.observableArray([]);
$.ajax({
url: '/DesktopModules/Blah/API/Data/GetTenQuickEntries',
type: 'GET',
dataType: 'json',
success: function (data) {
var mappedQuickEntries = $.map(data, function (item) {
return new QuickEntry(item.ItemPartNumb, item.ItemDescription);
});
self.quickEntries(mappedQuickEntries);
},
statusCode: {
404: function () {
alert('Failed');
}
}
});
};
ko.applyBindings(new QuickEntriesViewModel());
ItemPartNumb vs ItemPartNumber
And you are using the value-binding instead of the text-binding.
http://jsfiddle.net/MizardX/9sqvk/