Ajax loaded submit form not working - ajax

I am using Ajax to replace a part of my page with a partial view containing multiple submit forms. This normally works when I use a normal Html.BeginForm and reload the entire page (the submit forms loaded work). However, when using Ajax to load the submit form, they display normally on the page but are not working.
I have looked around for information, but the information I have found mainly concerns submitting form through Ajax call, not loading submit forms.
This is the main View containing the javascript.
#model List<SrrManager.Models.User>
#{
ViewBag.Title = "Create";
}
<script>
$(function () {
$('Body').keypress(function (e) {
if (e.which == 13) {
$('#nomButton').trigger('click');
}
});
$('#nomButton').keyup(function (e) {
if (e.which == 13) {
$('#nomButton').trigger('click');
}
});/*
$('#prenomButton').keypress(function (e) {
if (e.which == 13) {
$('#nomButton').trigger('click');
}
});*/
$("#nomButton").on('click', function () {
var givenName = $("#prenomBox").val();
var nom = $("#nomBox").val();
$.ajax({
url: '#Url.Action("Create", "ManageUser")', //+ "?firstname=" + givenName + "&lastname=" + lastname,
type: 'GET',
data: { prenom: givenName, nomFamille: nom },
success: function (result) {
$('#liste-user').replaceWith(result);
}
});
});
});
</script>
<body>
<h2>Add an user</h2>
<p>
<label class="label-form">Prenom :</label>#Html.TextBox("prenomBox")
<br />
<label class="label-form">Nom :</label> #Html.TextBox("nomBox")
<br />
<input type="button" value="Filter" id="nomButton" />
</p>
#Html.Partial("_Create", Model)
<div>
#Html.ActionLink("Back to List", "Index")
</div>
</body>
The _Create PartialView is as follow :
#model List<SrrManager.Models.User>
<div id="liste-user">
<table>
<tr>
<th>
First Name
</th>
<th>
Last Name
</th>
<th>
Email
</th>
<th>
Admin
</th>
<th></th>
</tr>
#foreach(var item in Model)
{
<tr>
<td>
#item.Name
</td>
<td>
#item.LastName
</td>
<td>
#item.email
</td>
#Html.Partial("__create", item)
</tr>
}
</table>
</div>
The last PartialView is used to create the submit form. The model is not a List but only User, and it is included once in each loop :
#model SrrManager.Models.User
#using(Html.BeginForm()){
<fieldset>
<legend>User</legend>
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#Html.HiddenFor(x => x.Name)
#Html.HiddenFor(x => x.LastName)
#Html.HiddenFor(x => x.email)
#Html.HiddenFor(x => x.account)
<td>
#Html.EditorFor(x => x.IsAdmin)
</td>
<td>
<input type="submit" value="save" />
</td>
</fieldset>
}
The list of user and the submit form is displayed normally using Ajax call or synchronous JQuery call when clicking on the Filter button, and the controller method is called as intended. However, the buttons work when loaded with synchronous JQuery calls, but not when loaded through Ajax.
The controller method is :
public ActionResult Create(string prenom ="", string nomFamille ="")
{
List<User> listeUser = new List<User>();
if (prenom.Equals("") && nomFamille.Equals(""))
{
}
else if (prenom.Equals(""))
{
string search = "*" + nomFamille + "*";
listeUser = SearchDirectory(search, 1);
}
else if (nomFamille.Equals(""))
{
string search = "*" + prenom + "*";
listeUser = SearchDirectory(search, 2);
}
else
{
string search = "*" + prenom + "*" + nomFamille + "*";
listeUser = SearchDirectory(search, 3);
}
if (Request.IsAjaxRequest())
{
return PartialView("_Create", listeUser);
}
return View(listeUser);
}
I am a beginner using Ajax, and I am at lost as to why it does not work. If any one has any lead, it would be very appreciated.

Try adding a jQuery handler for form submits.
$('form').submit(function () {
var givenName = $("#prenomBox").val();
var nom = $("#nomBox").val();
$.ajax({
url: '#Url.Action("Create", "ManageUser")', //+ "?firstname=" + givenName + "&lastname=" + lastname,
type: 'GET',
data: { prenom: givenName, nomFamille: nom },
success: function (result) {
$('#liste-user').html(result);
}
});
});

Related

.NET Core 6 Pull Down Menu Selection to Group through View Model

I am having partial success searching / grouping data through a viewmodel:
Partial Success:
URL Value
If I search on "B"
https://localhost:7207/Class01Name/Index2?String02NameSelected=B&SearchString=
Problem:
Not filtering data...simply changes pull down menu back to "All," displaying all data. Data not filtered.
**Question:
**
What in the code has to be changed to have the data filtered successfully?
Question is based on Tutorial at:
https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/search?view=aspnetcore-6.0
Model
using System.ComponentModel.DataAnnotations; // Date Format
namespace Project01Name.Models
{
public class Class01Name
{
public int Id { get; set; }
public string? String01Name { get; set; }
public string? String02Name { get; set; }
public int? Int01Name { get; set; }
public bool? Bool01Name { get; set; }
[DataType(DataType.Date)]
public DateTime? DateTime01Name { get; set; }
}
}
**
View Model
**
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;
namespace Project01Name.Models.ViewModelsName
{
public class SearchByGroupName
{
public List<Class01Name>? Class01NameList { get; set; } // A list of movies.
public SelectList? String02NameSelection { get; set; } // A SelectList containing the list of genres. This allows the user to select a genre from the list.
public string? String02NameSelected { get; set; } // MovieGenre, which contains the selected genre.
public string? SearchString { get; set; } // SearchString, which contains the text users enter in the search text box.
}
}
Controller Action Method
// GET: String01Names
public async Task<IActionResult> Index2(string class01NameGroup, string searchString)
{
// Use LINQ to get list of genres.
IQueryable<string> string02NameQuery = from m in _context.Class01Name
orderby m.String02Name
select m.String02Name;
var selectVariable = from m in _context.Class01Name
select m;
if (!string.IsNullOrEmpty(searchString))
{
selectVariable = selectVariable.Where(s => s.String01Name!.Contains(searchString));
}
if (!string.IsNullOrEmpty(class01NameGroup))
{
selectVariable = selectVariable.Where(x => x.String02Name == class01NameGroup);
}
var string02NameVM = new SearchByGroupName
{
String02NameSelection = new SelectList(await string02NameQuery.Distinct().ToListAsync()),
Class01NameList = await selectVariable.ToListAsync()
};
return View(string02NameVM);
}
View
#model Project01Name.Models.ViewModelsName.SearchByGroupName
#{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-action="Index2" method="get">
<div class="form-actions no-color">
<p>
<select asp-for="String02NameSelected" asp-items="Model.String02NameSelection"> <option value="">All</option></select>
Title: <input type="text" asp-for="SearchString" />
<input type="submit" value="Filter" />
#*<input type="submit" value="Search" class="btn btn-default" /> |
<a asp-action="Index">Back to Full List</a> *#
</p>
</div>
</form>
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Class01NameList[0].String01Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Class01NameList[0].String02Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Class01NameList[0].Int01Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Class01NameList[0].DateTime01Name)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.Class01NameList)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.String01Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.String02Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Int01Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.DateTime01Name)
</td>
<td>
<a asp-action="Edit" asp-route-id="#item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="#item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="#item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Partial Success:
URL Value
If I search on "B"
https://localhost:7207/Class01Name/Index2?String02NameSelected=B&SearchString=
Problem:
Not filtering data...simply changes pull down menu back to "All," displaying all data. Data not filtered.
**Question:
**
What in the code has to be changed to have the data filtered successfully?
Question is based on Tutorial at:
https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/search?view=aspnetcore-6.0
Not filtering data...simply changes pull down menu back to "All,"
displaying all data. Data not filtered.
**Question: ** What in the code has to be changed to have the data filtered successfully?
Well, seems you wanted to implement searching functionality in way, so that you can filter with the dropdown and search box and finally if you select All as dropdown value you want to load all the list without any filter and shorting means the full list which comes at first view.
If so, you need to use javascript for your dropdown change event as cshtml doesn't deal with change event. In addition, as you are using asp.net core MVC which would return HTML View altough, we need json data for Ajax reponse but we are would bee getting HTML View. So Ajax success Function will through an error where we would use filter with All parameter.
Modification Required:
Javascript:
#section scripts {
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<script src="https://cdn.datatables.net/1.11.3/js/jquery.dataTables.min.js"></script>
<script>
$(document).ready(function () {
$("#allId").change(function () {
alert("Click");
var allId = $('#allId').val();
console.log(allId);
if (allId == "All") {
alert("Alert");
$.ajax({
url: 'http://localhost:5094/Search/Index2',
type: 'GET',
dataType: 'json',
data: { String02NameSelected: "All", searchString: "" },
success: function (response) {
},
error: function () {
window.location.href = "#Url.Action("Index2", "Search")?String02NameSelected=All&SearchString=";
}
});
}
});
});
</script>
}
Note:
As you can see, in success function we are doing nothing, because it will always throuh an error because we are not returning json. Thus, we will work in error section. indow.location.href = "#Url.Action("Index2", "Search")?String02NameSelected=All&SearchString=";. Here, for your understanding, we will call this function when we select All as our dropdown value in that scenario, we will pass All and nothing , nothing will convert into null and all will be our search key.
Modify Your Existing View:
In your existing view, replace blow dropdown code snippet , means the select items
<select asp-for="String02NameSelected" id="allId" asp-items="Model.String02NameSelection"> <option value="All">All</option></select>
Note: If you notice I hav introduced a id id="allId" which will be using on dropdown change event.
Controller:
public async Task<IActionResult> Index2(string String02NameSelected, string searchString)
{
if (String02NameSelected == "All" && searchString == null)
{
var dataWithoutfileter = new SearchByGroupName();
dataWithoutfileter.String02NameSelection = new SelectList(String02NameSelectionList, "Text", "Value");
dataWithoutfileter.Class01NameList = listOfClass01Name;
return View(dataWithoutfileter);
}
if (!String.IsNullOrEmpty(String02NameSelected) && String02NameSelected !="All")
{
var objOfClass = new SearchByGroupName();
var string02NameQuery = listOfClass01Name.Where(m => m.String01Name.ToLower().Contains(String02NameSelected.ToLower()) || m.String02Name.ToLower().Contains(String02NameSelected.ToLower()));
objOfClass.Class01NameList = string02NameQuery.ToList();
objOfClass.String02NameSelection = new SelectList(String02NameSelectionList, "Text", "Value");
return View(objOfClass);
}
if (!String.IsNullOrEmpty(searchString))
{
var objOfClass = new SearchByGroupName();
var string02NameQuery = listOfClass01Name.Where(m => m.String01Name.ToLower().Contains(searchString.ToLower()) || m.String02Name.ToLower().Contains(searchString.ToLower()));
objOfClass.Class01NameList = string02NameQuery.ToList();
objOfClass.String02NameSelection = new SelectList(String02NameSelectionList, "Text", "Value");
return View(objOfClass);
}
//First loading
var objSearchByGroupName = new SearchByGroupName();
objSearchByGroupName.String02NameSelection = new SelectList(String02NameSelectionList, "Text", "Value");
objSearchByGroupName.Class01NameList = listOfClass01Name;
return View(objSearchByGroupName);
}
}
Complete Demo:
Full Controller With Seed Model Class Value:
public class SearchController : Controller
{
public static List<Class01Name> listOfClass01Name = new List<Class01Name>()
{
new Class01Name() { Id =101, String01Name ="Titanic",String02Name = "Romantic", Int01Name =01, Bool01Name = false, DateTime01Name = new DateTime(2023-01-15) },
new Class01Name() { Id =102, String01Name ="Forest gump",String02Name = "Motivational", Int01Name =02, Bool01Name = true, DateTime01Name = new DateTime(2023-01-12) },
new Class01Name() { Id =103, String01Name ="Spider Man",String02Name = "Action", Int01Name =03, Bool01Name = false, DateTime01Name = new DateTime(2023-01-10) },
new Class01Name() { Id =104, String01Name ="Harry Potter",String02Name = "Suspense", Int01Name =04, Bool01Name = true, DateTime01Name = new DateTime(2023-01-13)},
};
public List<SelectListItem> String02NameSelectionList = new List<SelectListItem>()
{
new SelectListItem { Text = "Motivational", Value = "Motivational" },
new SelectListItem { Text = "Romantic", Value = "Romantic" },
new SelectListItem { Text = "Action", Value = "Action" },
new SelectListItem { Text = "Comedy", Value = "Comedy" }
};
public async Task<IActionResult> Index2(string String02NameSelected, string searchString)
{
if (String02NameSelected == "All" && searchString == null)
{
var dataWithoutfileter = new SearchByGroupName();
dataWithoutfileter.String02NameSelection = new SelectList(String02NameSelectionList, "Text", "Value");
dataWithoutfileter.Class01NameList = listOfClass01Name;
return View(dataWithoutfileter);
}
if (!String.IsNullOrEmpty(String02NameSelected) && String02NameSelected !="All")
{
var objOfClass = new SearchByGroupName();
var string02NameQuery = listOfClass01Name.Where(m => m.String01Name.ToLower().Contains(String02NameSelected.ToLower()) || m.String02Name.ToLower().Contains(String02NameSelected.ToLower()));
objOfClass.Class01NameList = string02NameQuery.ToList();
objOfClass.String02NameSelection = new SelectList(String02NameSelectionList, "Text", "Value");
return View(objOfClass);
}
if (!String.IsNullOrEmpty(searchString))
{
var objOfClass = new SearchByGroupName();
var string02NameQuery = listOfClass01Name.Where(m => m.String01Name.ToLower().Contains(searchString.ToLower()) || m.String02Name.ToLower().Contains(searchString.ToLower()));
objOfClass.Class01NameList = string02NameQuery.ToList();
objOfClass.String02NameSelection = new SelectList(String02NameSelectionList, "Text", "Value");
return View(objOfClass);
}
//First loading
var objSearchByGroupName = new SearchByGroupName();
objSearchByGroupName.String02NameSelection = new SelectList(String02NameSelectionList, "Text", "Value");
objSearchByGroupName.Class01NameList = listOfClass01Name;
return View(objSearchByGroupName);
}
}
Full View:
#model DotNet6MVCWebApp.Controllers.SearchByGroupName
#{
ViewData["Title"] = "Index";
}
<form asp-action="Index2" method="get">
<div class="form-actions no-color">
<p>
<select asp-for="String02NameSelected" id="allId" asp-items="Model.String02NameSelection"> <option value="All">All</option></select>
Title: <input type="text" asp-for="SearchString" />
<input type="submit" name="searchString" />
</p>
</div>
</form>
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Class01NameList[0].String01Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Class01NameList[0].String02Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Class01NameList[0].Int01Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Class01NameList[0].DateTime01Name)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.Class01NameList)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.String01Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.String02Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Int01Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.DateTime01Name)
</td>
<td>
<a asp-action="Edit" asp-route-id="#item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="#item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="#item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
#section scripts {
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<script src="https://cdn.datatables.net/1.11.3/js/jquery.dataTables.min.js"></script>
<script>
$(document).ready(function () {
$("#allId").change(function () {
alert("Click");
var allId = $('#allId').val();
console.log(allId);
if (allId == "All") {
alert("Alert");
$.ajax({
url: 'http://localhost:5094/Search/Index2',
type: 'GET',
dataType: 'json',
data: { String02NameSelected: "All", searchString: "" },
success: function (response) {
},
error: function () {
window.location.href = "#Url.Action("Index2", "Search")?String02NameSelected=All&SearchString=";
}
});
}
});
});
</script>
}
Output:

How can I refresh my partial view on my parent index after a modal update to add new information?

I am certain this question has been asked before, I don't think there is anything unique about my situation but let me explain. I have my Index View (Parent), on that Index View there is a partial View Dataset Contacts "links" (child), I have an Add Contact button, which pops a Modal and allows me to submit the form data to add to the database, when I return I want to only refresh the partial view of links. Note: the Controller Action Dataset_Contacts below needs to fire in order to refresh the partial view (child). It might go without saying, but I don't see this happening with my current code. Any assistance will be appreciated.
on my Index View index.cshtml I have the following code to render my partial View
<div class="section_container2">
#{ Html.RenderAction("Dataset_Contacts", "Home"); }
</div>
Here is the controller:
[ChildActionOnly]
public ActionResult Dataset_Contacts()
{
// Retrieve contacts in the Dataset (Contact)
//Hosted web API REST Service base url
string Baseurl = "http://localhost:4251/";
var returned = new Dataset_Contact_View();
var dataset = new Dataset();
var contacts = new List<Contact>();
var contact_types = new List<Contact_Type>();
using (var client = new HttpClient())
{
dataset = JsonConvert.DeserializeObject<Dataset>(datasetResponse);
contact_types = JsonConvert.DeserializeObject<List<Contact_Type>>(ContactTypeResponse);
// Set up the UI
var ds_contact = new List<ContactView>();
foreach (Contact c in dataset.Contact)
{
foreach (Contact_Type t in contact_types)
{
if (c.Contact_Type_ID == t.Contact_Type_ID)
{
var cv = new ContactView();
cv.contact_id = c.Contact_ID;
cv.contact_type = t.Description;
returned.Dataset_Contacts.Add(cv);
}
}
}
}
return PartialView(returned);
}
Here is my Partial View Dataset_Contacts.cshtml
#model ResearchDataInventoryWeb.Models.Dataset_Contact_View
<table>
#{
var count = 1;
foreach (var ct in Model.Dataset_Contacts)
{
if (count == 1)
{
#Html.Raw("<tr>")
#Html.Raw("<td>")
<span class="link" style="margin-left:10px;">#ct.contact_type</span>
#Html.Raw("</td>")
count++;
}
else if (count == 2)
{
#Html.Raw("<td>")
<span class="link" style="margin-left:300px;">#ct.contact_type</span>
#Html.Raw("</td>")
#Html.Raw("</tr>")
count = 1;
}
}
}
</table>
Also on my Index.cshtml is my Add Contact button, which pops a modal
<div style="float:right;">
<span class="link" style="padding-right:5px;">Add</span>
</div>
jquery for the Modal:
var AddContact = function () {
var url = "../Home/AddContact"
$("#myModalBody").load(url, function () {
$("#myModal").modal("show");
})
};
Controller action for AddContact
public ActionResult AddContact()
{
return PartialView();
}
Modal for AddContact.cshtml
#model ResearchDataInventoryWeb.Models.Contact
<form id="contactForm1">
<div class="section_header2">Contact</div>
<div style="padding-top:5px;">
<table>
<tr>
<td>
<span class="display-label">UCID/Booth ID</span>
</td>
<td>
#Html.TextBoxFor(model => model.Booth_UCID, new { placeholder = "<Booth/UCID>", #class = "input-box" })
</td>
</tr>
<tr>
<td>
<span class="display-label">Type</span>
</td>
<td>
<select class="input-box" id="contact_type">
<option value="contact_type">Contact Type*</option>
<option value="dataset_admin">Dataset Admin</option>
<option value="dataset_Provider">Dataset Provider</option>
<option value="department">Department</option>
<option value="external_collaborator">External Collaborator</option>
<option value="principal_investigator">Principal Investigator</option>
<option value="research_center">Research Center</option>
<option value="vendor">Vendor</option>
</select>
</td>
</tr>
<tr>
<td>
<span class="display-label">Name</span>
</td>
<td>
#Html.TextBoxFor(model => model.First_Name, new { placeholder = "<First Name>", #class = "input-box-modal" })
#Html.TextBoxFor(model => model.Last_Name, new { placeholder = "<Last Name>", #class = "input-box-modal" })
</td>
</tr>
<tr>
<td>
<span class="display-label">Email</span>
</td>
<td>
#Html.TextBoxFor(model => model.Email, new { placeholder = "<Email 1>", #class = "input-box-modal" })
#Html.TextBoxFor(model => model.Email_2, new { placeholder = "<Email 2>", #class = "input-box-modal" })
</td>
</tr>
<tr>
<td>
<span class="display-label">Phone</span>
</td>
<td>
#Html.TextBoxFor(model => model.Phone_Number, new { placeholder = "<Phone 1>", #class = "input-box-modal" })
#Html.TextBoxFor(model => model.Phone_Number_2, new { placeholder = "<Phone 2>", #class = "input-box-modal" })
</td>
</tr>
<tr>
<td>
<span class="display-label">Job Title</span>
</td>
<td>
#Html.TextBoxFor(model => model.Title_Role, new { placeholder = "<Job Title>", #class = "input-box" })
</td>
</tr>
<tr>
<td>
<span class="display-label">Organization</span>
</td>
<td>
<input class="input-box" type="text" placeholder="<Organization>" />
</td>
</tr>
</table>
<div style="padding-left:10px; margin-top:10px;">
<textarea rows="3" placeholder="Notes"></textarea>
</div>
</div>
<div class="centerButton" style="margin-top: 30px;">
<div style="margin-left:30px">
<submit id="btnSubmit" class="btn btn-default btn-sm" style="padding:14px"><span class="smallText_red" style="padding:30px">SAVE</span></submit>
</div>
<div style="margin-left:30px">
<submit class="btn btn-default btn-sm" style="padding:14px"><span class="smallText_red" style="padding:30px">REMOVE</span></submit>
</div>
</div>
</form>
<script type="text/javascript">
$(document).ready(function () {
$("#btnSubmit").click(function () {
var frm = $('#contactForm1').serialize()
$.ajax({
type: "POST",
url: "/Home/AddContact/",
data: frm,
success: function () {
$("#myModal").modal("hide");
}
})
})
})
</script>
and lastly Action for [HttpPost] AddContact(Contact data)
[HttpPost]
public ActionResult AddContact(Contact data)
{
// Update the Database here
return View();
}
My solution:
1. Change ActionResult to JsonResult
{
// Update the Database code
// END
return Json(new
{
dbUpdateResult = "success"
});
}
2. In Ajax:
//Ajax code
...
success: function (ajaxRespond) {
if(ajaxRespond.dbUpdateResult == "success"){
$("#myModal").modal("hide");
reloadTable()
}
}
Then you can use 1:
function reloadTable(){
$('#CONTAINER_ID').load('#Url.Action("Dataset_Contacts", "Home")');
}
Or 2:
function reloadTable(){
let myurl = '#Url.Action("Dataset_Contacts", "Home")';
$.ajax({
type: "GET",
url: myurl,
success: function (data, textStatus, jqXHR) {
$("#CONTAINER_ID").html(data);
},
error: function (requestObject, error, errorThrown) {
console.log(requestObject, error, errorThrown);
alert("Error: can not update table")
}
});
}
So you reload your partial view after successful dbupdate. Please tell me, if I'm wrong...

ASP.NET MVC3: Ajax postback doesnot post complete data from the view

Hi Greetings for the day!
(1) The view model (MyViewModel.cs) which is bound to the view is as below...
public class MyViewModel
{
public int ParentId { get; set; } //property1
List<Item> ItemList {get; set;} //property2
public MyViewModel() //Constructor
{
ItemList=new List<Item>(); //creating an empty list of items
}
}
(2) I am calling an action method through ajax postback (from MyView.cshtml view) as below..
function AddItem() {
var form = $('#MyForm');
var serializedform = form.serialize();
$.ajax({
type: 'POST',
url: '#Url.Content("~/MyArea/MyController/AddItem")',
cache: false,
data: serializedform,
success: function (html) {$('#MyForm').html(html);}
});
}
The below button click will call the ajax postback...
<input type="button" value="Add" class="Previousbtn" onclick="AddItem()" />
(3) I have an action method in the (MyController.cs controller) as below...
public ActionResult AddItem(MyViewModel ViewModel)
{
ViewModel.ItemList.Add(new Item());
return View("MyView", ViewModel);
}
Now the issue is, after returning from the action, there is no data in the viewmodel. But i am able to get the data on third postback !! Can you pls suggest the solution..
The complete form code in the view is below...
#model MyViewModel
<script type="text/javascript" language="javascript">
function AddItem() {
var form = $('#MyForm');
var serializedform = form.serialize();
$.ajax({
type: 'POST',
url: '#Url.Content("~/MyArea/MyController/AddItem")',
cache: false,
data: serializedform,
success: function (html) {
$('#MyForm').html(html);
}
});
}
function RemoveItem() {
var form = $('#MyForm');
var serializedform = form.serialize();
$.ajax({
type: 'POST',
url: '#Url.Content("~/MyArea/MyController/RemoveItem")',
cache: false,
data: serializedform,
success: function (html) {
$('#MyForm').html(html);
}
});
}
function SaveItems() {
var form = $('#MyForm');
var serializedform = forModel.serialize();
$.ajax({
type: 'POST',
url: '#Url.Content("~/MyArea/MyController/SaveItems")',
cache: false,
data: serializedform,
success: function (html) {
$('#MyForm').html(html);
}
});
}
</script>
#using (Html.BeginForm("SaveItems", "MyController", FormMethod.Post, new { id = "MyForm" }))
{
#Html.HiddenFor(m => Model.ParentId)
<div>
<input type="button" value="Save" onclick="SaveItems()" />
</div>
<div>
<table>
<tr>
<td style="width: 48%;">
<div style="height: 500px; width: 100%; overflow: auto">
<table>
<thead>
<tr>
<th style="width: 80%;">
Item
</th>
<th style="width: 10%">
Select
</th>
</tr>
</thead>
#for (int i = 0; i < Model.ItemList.Count; i++)
{
#Html.HiddenFor(m => Model.ItemList[i].ItemId)
#Html.HiddenFor(m => Model.ItemList[i].ItemName)
<tr>
#if (Model.ItemList[i].ItemId > 0)
{
<td style="width: 80%; background-color:gray;">
#Html.DisplayFor(m => Model.ItemList[i].ItemName)
</td>
<td style="width: 10%; background-color:gray;">
<img src="#Url.Content("~/Images/tick.png")" alt="Added"/>
#Html.HiddenFor(m => Model.ItemList[i].IsSelected)
</td>
}
else
{
<td style="width: 80%;">
#Html.DisplayFor(m => Model.ItemList[i].ItemName)
</td>
<td style="width: 10%">
#if ((Model.ItemList[i].IsSelected != null) && (Model.ItemList[i].IsSelected != false))
{
<img src="#Url.Content("~/Images/tick.png")" alt="Added"/>
}
else
{
#Html.CheckBoxFor(m => Model.ItemList[i].IsSelected, new { #style = "cursor:pointer" })
}
</td>
}
</tr>
}
</table>
</div>
</td>
<td style="width: 4%; vertical-align: middle">
<input type="button" value="Add" onclick="AddItem()" />
<input type="button" value="Remove" onclick="RemoveItem()" />
</td>
</tr>
</table>
</div>
}
You must return PartialViewResult and then you can do something like
$.post('/controller/GetMyPartial',function(html){
$('elem').html(html);});
[HttpPost]
public PartialViewResult GetMyPartial(string id
{
return PartialView('view.cshtml',Model);
}
In my project i get state data with country id using json like this
in my view
<script type="text/javascript">
function cascadingdropdown() {
var countryID = $('#countryID').val();
$.ajax({
url: "/City/State",
dataType: 'json',
data: { countryId: countryID },
success: function (data) {
alert(data);
$("#stateID").empty();
$("#stateID").append("<option value='0'>--Select State--</option>");
$.each(data, function (index, optiondata) {
alert(optiondata.StateName);
$("#stateID").append("<option value='" + optiondata.ID + "'>" + optiondata.StateName + "</option>");
});
},
error: function () {
alert('Faild To Retrieve states.');
}
});
}
</script>
in my controller return data in json format
public JsonResult State(int countryId)
{
var stateList = CityRepository.GetList(countryId);
return Json(stateList, JsonRequestBehavior.AllowGet);
}
i think this will help you ....
I resolved the issue as below...
Issue:
The form code i have shown here is actually part of another view page
which also contains a form. So, when i saw the page source at
run-time, there are two form tags: one inside the other, and the
browser has ignored the inner form tag.
Solution:
In the parent view page, earlier i had used Html.Partial to render
this view by passing the model to it.
#using(Html.BeginForm())
{
---
---
#Html.Partial('/MyArea/Views/MyView',MyViewModel)
---
---
}
But now, i added a div with no content. On click of a button, i'm
calling an action method (through ajax postback) which then renders
the above shown view page (MyView.cshmtl) into this empty div.
#using(Html.BeginForm())
{
---
---
<div id="divMyView" style="display:none"></div>
---
---
}
That action returns a separate view which is loaded into the above
div. Since it is a separate view with its own form tag, i'm able to
send and receive data on each postback.
Thank you all for your suggestions on this :)

partial view refresh using jQuery

On my main edit view I have 3 partial views that contain child data for the main view model. I also have html text boxes for entering and saving related data such as notes etc.
After an item is entered or select and passed to a controller action, how do I refresh my partial views? Here is the code I have so far but it does not work. I think I need to pass a model back with my partial view?
I am using ajax to call my controller method.
Partial View:
#model cummins_db.Models.CaseComplaint
<table width="100%">
<tr>
<td>
#Html.DisplayFor(modelItem => Model.ComplaintCode.ComplaintCodeName)
</td>
<td>
#Html.DisplayFor(modelItem => Model.ComplaintCode.ComplaintType)
</td>
</tr>
</table>
This is the html where the partial view is located:
<div class="editor-label">
#Html.Label("Search and select a complaint code")
</div>
<div class="textarea-field">
<input id = "CodeByNumber" type="text" />
</div>
#Html.ActionLink("Refresh", "Edit", new { id = Model.CasesID })
<table width="100%">
<tr>
<th>Complaint Code</th>
<th>Complaint Description</th>
</tr>
#try
{
foreach (var comp_item in Model.CaseComplaint)
{
<div id="complaintlist">
#Html.Partial("_CaseComplaintCodes", comp_item)
</div>
}
}
catch
{
}
</table>
Here is the controller method that returns the partial view.
public ActionResult SelectForCase(int caseid, int compid, string compname)
{
if (ModelState.IsValid)
{
CaseComplaint c = new CaseComplaint
{
CasesID = caseid,
ComplaintCodeID = compid
};
db.CaseComplaints.Add(c);
db.SaveChanges();
}
return PartialView("_CaseComplaintCodes");
}
jQuery ajax calling the controller, it is part of an autocomplete function select.
$('#CodeByNumber').autocomplete(
{
source: function (request, response) {
$.ajax({
url: "/Cases/CodeByNumber", type: "GET", dataType: "json",
data: { searchText: request.term, maxResults: 10 },
contentType: "application/json; charset=utf-8",
success: function (data) {
response($.map(data, function (item) {
return {
label: item.ComplaintType,
value: item.ComplaintCodeName,
id: item.ComplaintCodeID
}; //return
}) //map
); //response
} //success
}); //ajax
}, //source
select: function (event, ui) {
var url = "/Cases/SelectForCase";
$.ajax({
type: "GET",
dataType: "html",
url: url,
data: { caseid: $('#CaseID').val(), compid: ui.item.id, compname: ui.item.label },
success: function (result) { $('#complaintlist').html(result); }
});
},
minLength: 1
});
Should the partial view not be as below:
#model cummins_db.Models.CaseComplaint
<table width="100%">
<tr>
<td>
#Html.DisplayFor(m => m.ComplaintCodeName)
</td>
<td>
#Html.DisplayFor(m => m.ComplaintType)
</td>
</tr>
</table>
This is what I ended up doing to make it work. I changed by controller action to this:
public ActionResult SelectForCase(int caseid, int compid)
{
if (ModelState.IsValid)
{
CaseComplaint c = new CaseComplaint
{
CasesID = caseid,
ComplaintCodeID = compid
};
db.CaseComplaints.Add(c);
db.SaveChanges();
var m = from d in db.CaseComplaints
where d.CasesID == caseid
select d;
return PartialView("_CaseComplaintCodes", m);
}
return PartialView("_CaseComplaintCodes");
}
It works now

Using jQuery and ASP.NET MVC together. Ajax post is not working?

I have a form submit with an AJAX post. It works fine.
But when I delete the item by clicking the delete link, I have an issue, a get request not post.
But from my javascript function, you can see I use jQuery css selctor to detect the link clicked or not, so I am confused.
Here is my code
My controller:
public class SessionsController : Controller
{
private SessionRepository _repository;
public SessionsController() : this(new SessionRepository()) { }
public SessionsController(SessionRepository repository)
{
_repository = repository;
}
public ActionResult Index()
{
var sessions = _repository.FindAll();
//for ajax requests, we simply need to render the partial
if (Request.IsAjaxRequest())
return PartialView("_sessionList2", sessions);
//return View("_sessionList", sessions);
return View(sessions);
}
[HttpPost]
public ActionResult Add(Session session)
{
_repository.SaveSession(session);
if (Request.IsAjaxRequest())
return Index();
return RedirectToAction("index");
}
[HttpPost]
public ActionResult Remove(Guid session_id)
{
_repository.RemoveSession(session_id);
return RedirectToAction("index");
}
}
The session view:
#model IEnumerable<MyMVCDemo.Models.Session>
<h2>Hijax Technique</h2>
<div id="session-list">
#{Html.RenderPartial("_sessionList2");}
</div>
<p>
</p>
#using (Html.BeginForm("add", "sessions", FormMethod.Post, new { #class = "hijax" }))
{
<fieldset>
<legend>Propose new session</legend>
<label for="title">Title</label>
<input type="text" name="title" />
<label for="description">Description</label>
<textarea name="description" rows="3" cols="30"></textarea>
<label for="level">Level</label>
<select name="level">
<option selected="selected" value="100">100</option>
<option value="200">200</option>
<option value="300">300</option>
<option value="400">400</option>
</select>
<br />
<input type="submit" value="Add" />
<span id="indicator" style="display:none"><img src="../../content/load.gif" alt="loading..." /></span>
</fieldset>
}
<label>
<input type="checkbox" id="use_ajax" />
Use Ajax?
</label>
<script src="../../Scripts/Common.js" type="text/javascript"></script>
My Partial View:
#model IEnumerable<MyMVCDemo.Models.Session>
<table id="sessions">
<tr>
<th>Title</th>
<th>Description</th>
<th>Level</th>
<th></th>
</tr>
#if(Model.Count() == 0) {
<tr>
<td colspan="4" align="center">There are no sessions. Add one below!</td>
</tr>
}
#foreach (var session in Model)
{
<tr>
<td>#session.Title</td>
<td>#session.Description</td>
<td>session.Level</td>
<td>
#Html.ActionLink("remove", "remove", new { session_id = session.Id }, new { #class = "delete" })
</td>
</tr>
}
This is my javascript which call the ajax post:
$('.delete').click(function () {
if (confirm('Are you sure you want to delete this item?')) {
$.ajax({
url: this.href,
type: 'POST',
success: function (result) {
$("#session-list").html(result);
}
});
return false;
}
return false;
});
$("form.hijax").submit(function (event) {
if ($("#use_ajax")[0].checked == false)
return;
event.preventDefault(); //prevent the actual form post
hijack(this, update_sessions, "html");
});
function hijack(form, callback, format) {
$("#indicator").show();
$.ajax({
url: form.action,
type: form.method,
dataType: format,
data: $(form).serialize(),
completed: $("#indicator").hide(),
success: callback
});
}
function update_sessions(result) {
//clear the form
$("form.hijax")[0].reset();
//update the table with the resulting HTML from the server
$("#session-list").html(result);
$("#message").hide().html("session added")
.fadeIn('slow', function () {
var e = this;
setTimeout(function () { $(e).fadeOut('slow'); }, 2000);
});
}
It looks to me like you do not rebind the click event after you update the partial.
What happends is that you replace the DOM(which the events are bound to) when you make the ajax call. So after you update post the form all your events are gone.
In jquery there is a live event that would help you here.
The code below is not tested some there might be some problems with it but it should give you an idea.
var sessionList = $('#session-list');
$('.delete', sessionList).live('click', function () {
if (confirm('Are you sure you want to delete this item?')) {
$.ajax({
url: this.href,
type: 'POST',
success: function (result) {
sessionList.html(result);
}
});
return false;
}
return false;
});
The selector $('.delete', sessionList) is to give the live function a context so it doesn't bubble events all the way to the top.

Resources