I'm trying to push an ajax response array into MVC table. This is how my script looks like:
<script type="text/javascript">
$(document).ready(function () {
$('#form1').submit(function (event) {
event.preventDefault();
event.returnValue = false;
var selectValue = $('#selectValue').val();
$.ajax({
url: "/api/Admin/GetDepotDetails/",
type: "POST",
data: { "selectValue": selectValue },
dataType: "json",
success: function (data) {
$("#Grid").html($(data).children());
},
error: function (jqXHR, textStatus, errorThrown) {
debugger;
alert(textStatus, errorThrown, jqXHR);
}
});
});
});
</script>
This is how my partial view looks like:
#model IEnumerable<SampleApp.DepotDetail>
<table class="table table-condensed" id="Grid">
<tr>
<th>
#Html.DisplayNameFor(model => model.DepotID)
</th>
<th>
#Html.DisplayNameFor(model => model.ColumnName)
</th>
<th>
#Html.DisplayNameFor(model => model.Country)
</th>
<th>
#Html.DisplayNameFor(model => model.CountryCode)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr class="warning">
<td>
#Html.DisplayFor(modelItem => item.DepotID)
</td>
<td>
#Html.DisplayFor(modelItem => item.ColumnName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Country)
</td>
<td>
#Html.DisplayFor(modelItem => item.CountryCode)
</td>
</tr>
}
</table>
This is how the WebApi method looks like:
[HttpPost]
public IEnumerable<DepotDetail> GetDepotDetails(Selected selectValue)
{
var model = depotsDetails.Where(x => x.ColumnName == selectValue.SelectValue) as IEnumerable<DepotDetail>;
var viewModel = new SearchViewModel{ DepotDetailsList = model, ActionLists = new ActionList()} ;
return model;
}
This is how the View looks like:
#model IEnumerable<SiemensSampleApp.DepotDetail>
<div class="row">
<div class="col-md-4">
<form id="form1">
#*#Html.DropDownListFor(model => model.DepotListSelectValue, Model.DepotLists, new { #class = "form-control" })*#
#Html.DropDownList("selectValue", new List<SelectListItem>
{
new SelectListItem() {Text = "Depot ID", Value="Depot ID"},
new SelectListItem() {Text = "Depot Name", Value="Depot Name"},
new SelectListItem() {Text = "Address", Value="Address"}
}, new { #class = "selectValue", #id = "selectValue" })
#*//, new { #class = "chzn-select", #id = "chzn-select" }*#
<input type="submit" value="submit" />
</form>
<br /><br /><br />
<table id="records_table" style="width:100%;"></table>
<div id="tableHere">
#{
if (Model == null)
{
Html.RenderPartial("_SearchResult", new List<DepotDetail>() { });
}
}
</div>
</div>
</div>
Question: Through WebApi i'm trying to get a List of details and bind it to a MVC table. What is the best way to do this?
I have used
$("#Grid").html($(data).children());
To fill the Grid. But the table doesn't have any data. can someone please give me an idea how to fill the grid using above Partial view.
Thank you in advance!
Your web api endpoint return data ( in json format), not the HTML markup from your partial view. You have 2 options.
1) Create an mvc action method which gets the data and pass it to your partial view and return the partial view response and use that to update your UI
[HttpPost]
public IEnumerable<DepotDetail> GetDepotDetails(Selected selectValue)
{
var model = depotsDetails.Where(x => x.ColumnName == selectValue.SelectValue)
as IEnumerable<DepotDetail>;
return PartialView(model);
}
Now make sure you have a partial view called GetDepotDetails.cshtml in ~/Views/Shared or ~/View/YourControllerName/. This view should be strongly typed to a collecction of DepotDetail.
#model IEnumerable<DepotDetail>
<p>Here loop through each item in Model and render the table</p>
<p> Same as your partial view in the question </p>
And in your success event,
success: function (data) {
$("#Grid").html(data);
},
2) Use your current web api endpoint and read the data in your ajax method's success event and dynamically build the html markup for the table rows and set that as the content of your Grid table.
success: function (data) {
var tblHtml="";
$.each(data.DepotDetailsList,function(a,b){
tblHtml+= "<tr><td>"+b.DepotID+"</td>";
tblHtml+= "<td>"+b.ColumnName+"</td>";
tblHtml+= "<td>"+b.Country+"</td>";
tblHtml+= "<td>"+b.CountryCode+"</td>M/tr>";
});
$("#Grid > tbody").html(tblHtml);
},
Since you already have the partial view which build the table, you can do this.
In your ajax success method call a controller action by passing this data received from the API. The controller will just return the existing partial view by passing the same model.
$.ajax({
url: "/api/Admin/GetDepotDetails/",
type: "POST",
data: { "selectValue": selectValue },
dataType: "json",
success: function (data) {
//$("#Grid").html($(data).children());
$.get("controller/Action",data.DepotDetailsList ,function(response){
$('#tableHolder').html(response) //have a div in your main view which will hold the table. Now the partial view has to be replaced into this div.
});
},
error: function (jqXHR, textStatus, errorThrown) {
debugger;
alert(textStatus, errorThrown, jqXHR);
}
});
So as I said, Create a new MVC action method and return a the same partial view by passing the model sent from ajax.
OR you can user Jquery and build the table again - But this is a pain if the table HTML is large (with css, attributes, dynamic arributes etc). - I think the other answer already has the details on this
Related
I build this code for select all checboxes and pass to controller, I using button when click it check all checkboxes and pick up all variables like (idtip, idemployee) trought array send to controller to update database table.
<tr>
<th>name</th>
<th>tips</th>
<th>
<button id="btnClick" class="btnClick">Select all</button>
</th>
</tr>
Here is my input and script.
#foreach (var item in (IEnumerable<cit.Models.getCheIdTip_Result>)Model)
{
<tr>
<td>#item.idtip</td>
<td>#item.tipname</td>
<td>
<div class="pure-checkbox" idtip="#item.idtip">
<input type="checkbox" idtip="#item.idtip" class="checktip"
checked="#(item.idemployee == ViewBag.idemployee ? true : false)"
name="#item.id.ToString()" id="#item.id.ToString()" />
<label for="#item.id.ToString()"></label>
</div>
</td>
</tr>
}
</table>
<input type="hidden" value="#ViewData["idemployee"]" name="idemployee" id="idemployee" class="idemployee" />
<script>
$('.pure-checkbox').click(function () {
$(this).parents('td').toggleClass('chked')
})
var wantedids = [idemployee,idtip]
$("#btnClick").click(function () {
for (var i = 0; i < $('.pure-checkbox').length; i++) {
if ($('.pure-checkbox').eq(i).parents('td').hasClass('chked')) {
wantedids.push(
$('.pure-checkbox').eq(i).attr('idtip')
)
}
}
$.post("UrlSettingsDocument.Tips", { ids: wantedids },
)
})
I using button when click it check all checkboxes and pick up all
variables like (idtip, idemployee) trought array send to controller to
update database table.
You could refer the following sample code:
Create a ViewModel to display records:
public class TestViewModel
{
public int id { get; set; }
public int idtip { get; set; }
public string idemployee { get; set; }
public bool isChecked { get; set; }
}
In the Controller, add the following actions:
//Set the initial data and return to view.
public IActionResult Default()
{
List<TestViewModel> items = new List<TestViewModel>()
{
new TestViewModel(){ id=101, idtip=1001, idemployee="AAA" },
new TestViewModel(){id=102,idtip=1002, idemployee="BBB" },
new TestViewModel(){id=103, idtip=1003, idemployee="CCC" },
new TestViewModel(){ id=104,idtip=1004, idemployee="DDD" },
new TestViewModel(){id=105, idtip=1005, idemployee="EEE" }
};
ViewBag.idemployee = "CCC"; //set the default checked item.
return View(items);
}
public IActionResult AddItems(IEnumerable<TestViewModel> items)
{
//insert the items into database.
return Ok("OK");
}
Then, in the View page (Default.cshtml), using the following code to display the content:
Here we can use a select all checkbox, after checking it, will select all items.
#model IEnumerable<WebApplication.Models.TestViewModel>
#{
ViewData["Title"] = "Default";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<table class="table">
<thead>
<tr>
<th>
<input type="checkbox" id="btnSelectAll" class="btnClick" /> <label for="btnSelectAll">Select All</label>
</th>
<th>
#Html.DisplayNameFor(model => model.idtip)
</th>
<th>
#Html.DisplayNameFor(model => model.idemployee)
</th>
<th>
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model) {
<tr>
<td>
<div class="pure-checkbox" idtip="#item.idtip">
<input type="checkbox" idtip="#item.idtip" data-idemployee="#item.idemployee" class="checktip"
checked="#(item.idemployee == ViewBag.idemployee ? true : false)"
name="#item.id.ToString()" id="#item.id.ToString()" />
<label for="#item.id.ToString()"></label>
</div>
</td>
<td>
#Html.DisplayFor(modelItem => item.idtip)
</td>
<td>
#Html.DisplayFor(modelItem => item.idemployee)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
</td>
</tr>
}
</tbody>
</table>
<button id="btnSubmit" class="btnClick">Submit</button>
At the end of the Default.cshtml page, using the following script to achieve the select all function and submit the records to the controller.
#section Scripts{
<script>
$(function () {
//If checked the select all checkbox, select all items. else unchecked.
$("#btnSelectAll").click(function () {
if ($(this).is(":checked")) {
$(".checktip").each(function (index, item) {
$(item).prop("checked", true);
});
}
else {
$(".checktip").each(function (index, item) {
$(item).prop("checked", false);
});
}
});
$("#btnSubmit").click(function () {
var testViewModels = [];
//using the class selector to loop through the checkbox list and get all items, if you want to get the checked items, add an if...else statement in the each function.
$(".checktip").each(function (index, item) {
var TestViewModel = {};
TestViewModel.idtip = $(this).attr("idtip");
TestViewModel.idemployee = $(this).attr("data-idemployee");
TestViewModel.isChecked = $(this).is(":checked");
testViewModels.push(TestViewModel);
});
$.ajax({
type: "Post",
url: "/Home/AddItems", //remember change the controller to your owns.
data: { items: testViewModels }, //the name ("items") should be the same with the parameter's name in the controller.
success: function (data) {
console.log(data)
},
error: function (response) {
console.log(response.responseText);
}
});
});
});
</script>
}
The result as below:
I want to send multiple records in the database using javascript in asp.net mvc i tried many different ways but all in vain. here I have the best code which can send the data to the controller but the file is not sending.
I search different ways i have found one is with FormData but i am unable to handle that in this context.
Controller:
public ActionResult SaveAllFeedback(FEEDBACKVM[] fEEDBACKs)
{
try
{
if (fEEDBACKs != null)
{
FEEDBACK fEEDBACK = new FEEDBACK();
foreach (var item in fEEDBACKs)
{
fEEDBACK.DATE = item.DATE;
fEEDBACK.COMMENT = item.COMMENT;
fEEDBACK.STUDENTID = item.STUDENTID;
fEEDBACK.TEACHERID = db.TEACHERs.Where(x => x.EMAIL == User.Identity.Name).FirstOrDefault().ID;
if (item.HOMEWORK != null)
{
fEEDBACK.HOMEWORK = SaveToPhysicalLocation(item.HOMEWORK);
}
db.FEEDBACKs.Add(fEEDBACK);
}
db.SaveChanges();
return Json("Done", JsonRequestBehavior.AllowGet);
}
return Json("Unable to save your feedback! Please Provice correct information", JsonRequestBehavior.AllowGet);
}
catch (Exception)
{
return Json("Unable to save your feedback! Please try again later.", JsonRequestBehavior.AllowGet);
}
}
ViewPage:
<form>
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
<input name="DATE" id="DATE" type="date" class="form-control" />
</div>
<table class="table table-responsive table-hover" id="table1">
<thead>
<tr class="bg-cyan">
<th></th>
<th>RollNumber</th>
<th>Comment</th>
<th>Homework</th>
</tr>
</thead>
<tbody>
#foreach (var item in ViewBag.students)
{
<tr>
<td>
<input name="STUDENTID" type="text" value="#item.Key" hidden="hidden" />
</td>
<td>
<input name="STUDENTROLLNUMBER" type="text" value="#item.Value" class="form-control" readonly="readonly" />
</td>
<td>
<input name="COMMENT" type="text" class="form-control" />
</td>
<td>
<input name="HOMEWORK" type="file" class="form-control" />
</td>
</tr>
}
</tbody>
</table>
<div class="form-group">
<div class="col-md-10">
#Html.ValidationMessage("ErrorInfo", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button id="saveButton" type="submit" class="btn btn-danger">Save Attendance</button>
</div>
</div>
</form>
Script:
<script>
//After Click Save Button Pass All Data View To Controller For Save Database
function saveButton(data) {
return $.ajax({
contentType: 'application/json; charset=utf-8',
dataType: 'json',
type: 'POST',
url: '#Url.Action("SaveAllFeedback", "Teacherss")',
data: data,
success: function (result) {
alert(result);
location.reload();
},
error: function () {
alert("Error!")
}
});
}
//Collect Multiple Order List For Pass To Controller
$("#saveButton").click(function (e) {
e.preventDefault();
var formData = new FormData();
var arr = [];
arr.length = 0;
$.each($("#table1 tbody tr"), function () {
//arr.push({
// //DATE: $("#DATE").val(),
// //STUDENTID: $(this).find('td:eq(0) input').val(),
// //COMMENT: $(this).find('td:eq(2) input').val(),
// //HOMEWORK: $(this).find('td:eq(3) input').val()
// });
formData.append("DATE", $("#DATE").val());
formData.append("STUDENTID", $(this).find('td:eq(0) input').val());
formData.append("COMMENT", $(this).find('td:eq(2) input').val());
formData.append("HOMEWORK", $(this).find('td:eq(3) input')[0].files[0]);
});
var data = JSON.stringify({
fEEDBACKs: formData
});
$.when(saveButton (data)).then(function (response) {
console.log(response);
}).fail(function (err) {
console.log(err);
});
});
</script>
I just want to send multiple records with the file to the database
are you sure you want send the files???? if yes then
Your form tag should be look like this
<form id="yourid" action="youraction" enctype="multipart/form-data">
Form Component
</form>
NOTE:- enctype="multipart/form-data" tag is important
and then controller should be look like this
public ActionResult YourController(FormCollection data)
{
if (Request.Files.Count > 0)
{
foreach (string fileName in Request.Files)
{
HttpPostedFileBase file = Request.Files[fileName];
//you can save the file like this
string path = Server.MapPath("~/Yourpath/FileName" + fileName.Substring(fileName.LastIndexOf('.')));
file.SaveAs(path);
//or you can load it to memory like this
MemoryStream ms = new MemoryStream();
file.InputStream.CopyTo(ms);
//use it how you like
}
}
return View();
}
Currently, my view looks something like:
#using (Html.BeginForm("CreateUser", "Home", FormMethod.Post))
{<form ng-controller="MyController">
<table cellpadding="2" cellspacing="2">
<tr>
<td>#Html.LabelFor(model => model.FirstName) </td>
<td>#Html.TextBoxFor(model => model.FirstName, new { ng_model = "user.firstName" }) </td>
</tr>
<tr>
<td>#Html.LabelFor(model => model.LastName) </td>
<td>#Html.TextBoxFor(model => model.LastName, new { ng_model = "user.lastName" })) </td>
</tr>
<tr>
<td> </td>
<td><input type="submit" value="Save" ng-click="addUser()" /></td>
</tr>
</table>
</form>
}
My Controller (on ASP.NET MVC side):
[HttpPost]
public ActionResult Create(UsersViM usersVM)
{
//Sets the model equal to viewmodel
//Saves the name in session and redirects to previous view with new list of names.
}
I am wondering, what data should I be passing from my view to my controller? That is, how do I pass my model from my view to my controller? How do I set that up in angular?
$scope.addUser = function() {
var data = {
//user.firstname, user.lastname but how does angular know what user is?
//User is defined as the Model on the ASP.NET MVC side.
};
$http
.post('Home/Create', data)
.success(function(data, status, headers, config) {
})
.errors(function(data, status, headers, config) {
});
};
$scope.addUser = function () {
$http
.post('Home/CreateUser', usersViewModel)
.success(function (data, status, headers, config) {
successFn();
})
.errors(function (data, status, headers, config) {
errorFn();
});
};
Your back-end model fields should be same as like front-end model fields so that the mapping will not generate an error.
Suppose if you have defined you scope as mentioned below then define the user property so that angular can bind it with ng-model properties.
function MyController($scope) {
$scope.user= {};
$scope.addUser= function() {
console.log(this.user);
......
};
}
When the above form is submitted $scope.addUser will contain an object of your form which can then be passed in your http post request. e.g:
Object {firstName: "Test First Name", lastName: "Test Last Name"}
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
I am working on an asp.net mvc web application, and i have the following main view:-
<div class="box-content">
#using (Ajax.BeginForm("AssignCustomer", "Firewall", new AjaxOptions
{
InsertionMode = InsertionMode.InsertAfter,
UpdateTargetId = "Customertable",
LoadingElementId = "progress",
HttpMethod= "POST",
OnSuccess="submitform"
}))
{
#Html.ValidationSummary(true)
#Html.AntiForgeryToken()
#Html.HiddenFor(model=>model.FirewallCustomer.ID)
<div>
<span class="f">Customer Name</span>
#Html.TextBoxFor(model => model.FirewallCustomer.CustomerName, new { data_autocomplete_source = Url.Action("CustomerAutoComplete", "Firewall") })
#Html.ValidationMessageFor(model => model.FirewallCustomer.CustomerName)
</div>
<input type="submit" value="Save" class="btn btn-primary"/>
}
<p><img src="~/Content/Ajax-loader-bar.gif" class="loadingimage" id="progress" /></p>
<table class="table table-striped table-bordered bootstrap-datatable datatable">
<thead>
<tr>
<th class="f"> Customer Name </th>
</tr></thead>
<tbody id="Customertable">
#foreach(var info in Model.Firewall.FirewallCustomers.OrderBy(a=>a.CustomerName)){
<tr id= "#info.CustomerName">
<td> #Html.ActionLink(info.CustomerName, "Index", "Customer", new {searchTerm=info.CustomerName},null)</td>
<td></td>
</tr>
}
</tbody>
</table> </div></div></div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
which calls the following action method when submitting the Ajax.begin form:-
[HttpPost]
[ValidateAntiForgeryToken]
[CheckUserPermissions(Action = "Edit", Model = "Firewall")]
public ActionResult AssignCustomer([Bind(Include = "FirewallCustomer")] FirewallJoin fc)
{
fc.FirewallCustomer.CustomerName = fc.FirewallCustomer.CustomerName.Trim();
if (ModelState.IsValid)
{
try
{
repository.InsertOrUpdateFirewallCustomer(fc.FirewallCustomer,ADusername);
repository.Save();
return View("_customerrow", fc.FirewallCustomer);
and the returned partial view from the action method call, (which should be inserted after the table body) looks as follow:-
#model TMS.Models.FirewallCustomer
<tr id="#Model.CustomerName.ToString()">
<td>#Model.CustomerName</td>
<td>
#Ajax.ActionLink("Delete",
"DeleteCustomerFirewall", "Firewall",
new { firewallid = Model.ID, customername = Model.CustomerName},
new AjaxOptions
{ Confirm = "Are You sure You want to delete " + Model.CustomerName,
HttpMethod = "Post",
OnSuccess = "deletionconfirmation",
OnFailure = "deletionerror"
})
</td>
</tr>
now when i click on the ajax.beginform insdie my main view the record will be added to the DB, but the partial view will not returned , instead i will get the folloiwng exception :-
0x80020101 - JavaScript runtime error: Could not complete the operation due to error 80020101.
And the the jquery 1.8.2 will throw an exception (throw e) on the following code:-
if ( !transport ) {
done( -1, "No Transport" );
} else {
jqXHR.readyState = 1;
// Send global event
if ( fireGlobals ) {
globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
}
// Timeout
if ( s.async && s.timeout > 0 ) {
timeoutTimer = setTimeout( function(){
jqXHR.abort( "timeout" );
}, s.timeout );
}
try {
state = 1;
transport.send( requestHeaders, done );
} catch (e) {
// Propagate exception as error if not done
if ( state < 2 ) {
done( -1, e );
// Simply rethrow otherwise
} else {
throw e;
}
}
Can anyone adivce what is causing this problem ?
All the error 80020101 means is that there was an error, of some sort, while evaluating JavaScript. If you load that JavaScript via Ajax, the evaluation process is particularly strict.
Sometimes removing // will fix the issue, but the inverse is not true... the issue is not always caused by //.
Look at the exact JavaScript being returned by your Ajax call and look for any issues in that script. For more details see a great writeup here
http://mattwhite.me/blog/2010/4/21/tracking-down-error-80020101-in-internet-exploder.html