Looping through dynamic forms and submitting each onclick with Ajax? - c#

I am dynamically populating form(s) in my view (MVC) and I can have one or many forms on the same page. Each form is uniquely named, however the field variables in each form remain the same.
It works a treat with each form having its own submit button and passing the input to my Post Controller method, but now I need to add the option to submit all or one form by clicking the "next page" link. As I already have JQuery loading, I am trying to do this with Ajax and Json but I am stuck.
View
#using Microsoft.AspNet.Identity
#model IEnumerable<Template.Models.GetViewModel>
#{
ViewBag.Title = "About me";
ViewBag.Page = Model.First().PageNumber;
}
#Html.AntiForgeryToken();
#foreach (var q in Model.OrderBy(o => o.QuestionRanking))
{
var qtype = q.QuestionTypeId;
Html.BeginForm("ViewQuestion", "Question", FormMethod.Post, new { #class = #q.ShowHide + " form-horizontal", id = #q.FormNumber, role = "form" });
<div>
<h1>#q.QuestionRanking. #q.Question1</h1>
</div>
<div class="form-group">
#Html.TextArea("Answer", q.Answer, new { #class = "form-control", rows = "4", cols = "10" })
</div>
<div class="form-group">
<input type="submit" name="#q.FormNumber" class="btn btn-primary" value="Save answer" />
</div>
<hr />
Html.EndForm();
}
<p>
#Html.ActionLink("Previous", "ViewQuestion", new { page = ViewBag.Page - 1 }) |
#Html.ActionLink("Next", "ViewQuestion", new { page = ViewBag.Page + 1 })
</p>
#section Scripts {
#Scripts.Render("~/bundles/jquery")
}
The controller
[HttpPost]
public ActionResult ViewQuestion([Bind(Include = "QuestionId, UserId")] ResponseViewModel responseViewModel)
{
var page = System.Web.HttpContext.Current.Request["page"];
var newAnswer = System.Web.HttpContext.Current.Request["Answer"];
var re = new Response
{
Answer = newAnswer,
UserId = responseViewModel.UserId,
QuestionId = responseViewModel.QuestionId,
};
_db.Responses.Add(re);
_db.SaveChanges();
}
I haven't gotten very far with my script and I am lost as to how to get the values to my controller;
<script>
function postValues() {
var str = $( "form" ).serialize();
$( "#results" ).text( str );
}
</script>
Any advice or examples would be greatly appreciated.

To use ajax you can convert your forms using the following
#using(Ajax.BeginForm("ViewQuestion","Question",null,new AjaxOptions{ options here },
new { #class = #q.ShowHide + " form-horizontal", id = #q.FormNumber, role = "form"
}))
{
#Html.AntiForgeryToken();
<div>
<h1>#q.QuestionRanking. #q.Question1</h1>
</div>
<div class="form-group">
#Html.TextArea("Answer", q.Answer, new { #class = "form-control", rows = "4",
cols = "10" })
</div>
<div class="form-group">
<input type="submit" name="#q.FormNumber" class="btn btn-primary"
value="Save answer" />
</div>
<hr />
}
then you can use jquery to submit each form
$('form').each(function(){
$(this).submit();
});
with regards to #Html.AntiForgeryToken(); this should be within each form, and if you want to use it you need to add [ValidateAntiForgeryToken] to your controller action

Related

Multiple drop down lists with same name pre-selecting different values

I have an MVC application that accepts a list of Manager IDs for a given department. Each department can have zero or more managers. To achieve this, there is an initial drop down list with all available managers. If the user wishes to add another manager, the "Add Manager button is clicked, an ajax request is made to a partial view that returns a new list of managers (with the name control name, but a different ID value). When the user submits the form, the array of manager IDs can be accessed easily, but when editing, any attempt to pre-select the entry in the drop down results in ALL drop downs having the same selected entry. I believe this is due to the drop downs all having the same name.
I've tried pre-selecting the listitem in both the generation of the drop down list, and in the controller, neither works.
ViewModel:
public class AddDepartmentVM
{
// Form data
public List<int> ManagerIDs { get; set; }
}
Initial View:
using (Html.BeginForm("AddDepartment", "Departments", FormMethod.Post, new { id = "addDepartment", className = "form", role = "form" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, null, new { #class = "text-danger" })
// Hide the ID field
#Html.HiddenFor(model => model.ID);
<div class="form-row container">
<div class="row">
<div class="col-sm">
<label for="Description">Department Name</label>
</div>
<div class="col-sm">
#Html.EditorFor(model => model.Description, new { #class = "test-class", aria_describedby = "descriptionHelp", placeholder = Html.DisplayNameFor(model => model.Description) })
<small id="descriptionHelp" class="form-text text-muted">Department names should be approved by Corporate &amp IT.</small>
#Html.ValidationMessageFor(model => model.Description, null, new { #class = "text-danger" })
</div>
</div>
<div class="row">
<div class="col-sm">
<label for="RecordStatusID">Status</label>
</div>
<div class="col-sm">
#Html.DropDownListFor(model => model.RecordStatusID, new SelectList(recordStatuses.SearchResults, "ID", "Description"), new { #class = "some-class" })
#Html.ValidationMessageFor(model => model.RecordStatusID, null, new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-row container">
<div class="row">
<div class="col-sm">
<label for="Manager">Manager</label>
</div>
<div class="col-sm">
#for (int index = 0; index < managerCount; index++)
{
// Declarations
int selectedID = (Model.ManagerIDs != null && Model.ManagerIDs[index] != 0) ? Model.ManagerIDs[index] : 0;
// If this was an actual manager
if (Model.ManagerIDs != null && Model.ManagerIDs[index] != 0)
{
// Save the selctedID
selectedID = Model.ManagerIDs[index];
}
<div>
#Html.DropDownListFor(model => model.ManagerIDs, ViewData["managerList" + index.ToString()] as SelectList, "- Select -", new { #class = "some-class manager-list", id = "ManagerIDs[" + index + "]" })
<a class="btn btn-danger delete-manager disabled" href="#" role="button" disabled>Delete</a>
</div>
}
<a id="addManager" class="btn btn-primary add-manager disabled" href="#" role="button" disabled>Add Manager</a>
</div>
</div>
</div>
Partial View:
#{
// Page setup
Layout = null;
// Get the drop down field values from the ViewData object
ContactsSearchResultsVM managerList = ViewData["managerList"] as ContactsSearchResultsVM;
// Declarations
string controlID = "ManagerIDs[" + ViewBag.ManagerID + "]";
}
<div>
#Html.DropDownList("ManagerIDs", new SelectList(managerList.SearchResults, "ID", "ShortDisplayName"), "- Select -", new { #class = "some-class manager-list", id = controlID })
<a class="btn btn-danger delete-manager disabled" href="#" role="button" disabled>Delete</a>
</div>
Controller:
public ActionResult AddDepartment(AddDepartmentVM viewModel)
{
// Declarations
bool result = false;
ContactsSearchResultsVM managerList = new ContactsSearchResultsVM(0, 0, 0, 0, null);
RecordStatusXRefSearchResultsVM recordStatuses = new RecordStatusXRefSearchResultsVM(0, 0, 0, 0, null);
try
{
// Get a list of all possible managers
managerList = ContactsSearch.SearchContactsTableQuick(new ContactsSearchCriteria
{
FromCache = true,
CacheResults = true,
CacheDurationInMinutes = 60
});
// Get a list of statuses
recordStatuses = RecordStatusXRefSearch.SearchRecordStatusXRefTable(
new RecordStatusXRefSearchCriteria
{
ExcludeIDs = new List<int>() { 0 }
});
ViewData["managerList"] = managerList;
ViewData["recordStatuses"] = recordStatuses;
for (int i = 0; i < viewModel.ManagerIDs.Count; i++)
{
ViewData["managerList" + i.ToString()] = new SelectList(managerList.SearchResults, "ID", "ShortDisplayName", viewModel.ManagerIDs[i]);
}
// Return the view
return View("AddDepartment", viewModel);
Clicking on the Add Manager button will make a call back to the server to the partial view, get the HTML and append that to the form. Everything is working to submit the data, it's just the pre-selecting of the submitted values in the drop downs that isn't working.
I could do it in jQuery, but I figured I'd try to do it in the initial render if possible.
Well, all I had to do was change the front end value to model.ManagerIDs[index] and it worked.

MVC Pass value from view to dynamic partial view

I'm trying to make a partial view, which will add dynamically as much fields as I input. I input number of fields, then I want to choose days of week in formed fields and do some work with this data in controller, but I have a problem with passing amount of days in partial view.
Controller :
public class CoursesController : Controller
{
private SchoolContext db = new SchoolContext();
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create([Bind(Include = "CourseId,Name,Language,LanguageProficiency,StartDate,EndDate,TeacherId,NumberOfLessonsPerWeek")] Course course)
{
if (ModelState.IsValid)
{
db.Courses.Add(course);
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(course);
}
public ActionResult ShowDaysOfweek(int? countDays)
{
//countDays = 2;
ViewBag.CountDays = countDays;
var days = new List<DayOfWeek> { DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday, DayOfWeek.Saturday, DayOfWeek.Sunday };
ViewBag.DaysOfWeek = new SelectList(days);
return PartialView("ShowDaysOfweek");
}
}
In this View I can add patial view by clicking button in script:
#model SchoolManagementSystem.Models.Course
#using (Ajax.BeginForm(new AjaxOptions { }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" }
<div class="form-group">
#Html.Label("Number Of Lessons Per Week", htmlAttributes: new { #class = "control-label col-md-3" })
<div class="col-md-5">
#Html.TextBox("NumberOfLessonsPerWeek", null, htmlAttributes: new { #class = "form-control", #type = "number", #id = "numberOfLessonsPerWeek" })
</div>
<div>
<input type="button" value="Add days" id="Show" class="btn btn-default" />
</div>
</div>
<div id="ShowResults">
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<script type="text/javascript">
var url = '#Url.Action("ShowDaysOfweek", "Courses")';
$('#Show').on("click", function () {
var countDays = $('#numberOfLessonsPerWeek').val();
url += '/?countDays=' + countDays;
$('#ShowResults').load(url);
})
</script>
Partial view:
#for (var i = 0; i < ViewBag.CountDays; i++)
{
<div class="form-group">
#Html.Label("Day of week", htmlAttributes: new { #class = "control-label col-md-3" })
<div class="col-md-5">
#Html.DropDownList("DaysOfWeek", (IEnumerable<SelectListItem>)ViewBag.DaysOfWeek, htmlAttributes: new { #class = "form-control", style = "height: 35px" })
</div>
</div>
}
Is it possible to do something? Thanks!
First create the hidden field with partial view url
<input type="hidden" value="#Url.Action("ShowDaysOfweek", "Courses", new { countDays= "numberOfLessonsPerWeek" })" id="hdnURLShowDaysOfweek" />
in javascript read the url and replace the parameter
<script type="text/javascript">
var url = $('#hdnURLShowDaysOfweek').val();
$('#Show').on("click", function () {
url = url.replace("numberOfLessonsPerWeek",$('#numberOfLessonsPerWeek').val());
$('#ShowResults').load(url);
})
</script>

How can I return a view from another model in a controller?

I stumbled across a better way to display my comment form within the post window with <p id="createPostButton">#Html.Action("Create", "Comment", new { id = Model.PostId })</p> (I was originally just trying to create a button to take you to the comment page sending the post id). However, I now get an error when I try to pass back the post/details/{id} view in the CommentController. It keeps trying to look in comment or shared folders passing either post OR details/{id} instead of post/details/{id}.
Post/Details Razor HTML file:
#model FantaC.Models.Post
#{
ViewBag.Title = #Html.DisplayFor(model => model.PostName);
}
<h2>#Html.DisplayFor(model => model.PostName)</h2>
<div class="row">
<div class="col-md-8 whiteBorder scroll">
<div class="postName">
<h4>Written by: #Html.DisplayFor(model => model.UserName)</h4>
<img src="#Html.DisplayFor(model => model.PostImage)" />
</div>
<div class="postContent">
<p>#Html.DisplayFor(model => model.PostContent)</p>
</div>
</div>
<div class="col-md-4 whiteBorder scroll">
<h4>Comments</h4>
#foreach (var comment in Model.PostComments)
{
<h5>#Html.DisplayFor(modelItem => comment.UserName)</h5>
<h5>#Html.DisplayFor(modelItem => comment.CommentSubject)</h5>
<p>#Html.DisplayFor(modelItem => comment.CommentContent)</p>
<p>
#Html.ActionLink("Edit", "../Comment/Edit", new { id = comment.CommentId }) |
#Html.ActionLink("Details", "../Comment/Details", new { id = comment.CommentId }) |
#Html.ActionLink("Delete", "../Comment/Delete", new { id = comment.CommentId })
</p>
}
<p id="createPostButton">#Html.Action("Create", "Comment", new { id = Model.PostId })</p> <!--**********This is the line that is important-->
#*#=Html.RenderAction("Create", "Comments", new { postId = Model.PostId });*#
#*#Html.Partial("Comments")*#
</div>
</div>
<p>
#*#Html.ActionLink("Add a Comment", "Create", "Comment")*#
#Html.ActionLink("Comment", "Create", "Comment", new { id = Model.PostId }, null) |
#Html.ActionLink("Back to List", "Index")
The Comment/Create Razor HTML file that is getting pulled in by the Html.Action:
#model FantaC.Models.Comment
#{
Layout = null;
}
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Comment</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.CommentSubject, htmlAttributes: new { #class = "control-label col-md-10 displayBlock" })
<div class="col-md-12">
#Html.EditorFor(model => model.CommentSubject, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.CommentSubject, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CommentContent, htmlAttributes: new { #class = "control-label col-md-10 displayBlock" })
<div class="col-md-12">
#Html.EditorFor(model => model.CommentContent, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.CommentContent, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
#*<div>
#Html.ActionLink("Back to List", "Index")
</div>*#
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
The important section from the CommentController:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(string id, [Bind(Include = "CommentSubject,CommentContent")] Comment model)
{
if (ModelState.IsValid)
{
ApplicationUser user = System.Web.HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>().FindById(System.Web.HttpContext.Current.User.Identity.GetUserId());
var commentId = (23817 + db.Comment.Count()).ToString().PadLeft(10, '0');
var comment = new Comment
{
CommentId = commentId,
PostId = id,
UserName = user.UserName,
PostTime = DateTime.Now,
CommentSubject = model.CommentSubject,
CommentContent = model.CommentContent
};
db.Comment.Add(comment);
db.SaveChanges();
return View("Details/" + id, "Post");
}
return View(model);
}
I also tried return View("../post/details/" + id); to no avail. How can I get back up to the post view url (post/details/{id} from the CommentController?
As a side note, I had it almost working by taking out the returns and making the method void, but after clicking the submit comment button the whole comment/create form would disappear. I would be fine going back to that way of doing things if anyone knows a way to make the form stay after clicking the create comment button.
Thanks for any help! :)
Edit:
I forgot to mention that I tried this too. It returns an error that looks like this:
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: Child actions are not allowed to perform redirect actions.
Source Error:
Line 32: }
Line 33:
Line 34: #Html.Action("Create", "Comment", new { id = Model.PostId })
Line 35:
You should follow the PRG (POST-REDIRECT-GET) pattern. After saving the comment, you should redirect to the post details page.
You may use the RedirectToAction method to return a RedirectResponse back to the browser which will make a new GET request to the post details action method.
So replace
return View("Details/" + id, "Post");
with
return RedirectToAction("Details" , "Post", new {id=id});

How can I refresh a partial view on the main index page on a submit from a separate partial view modal

I have a main index page that loads a partial view that contains a dropdownfor list. The selection of an item from the ddl populates controls in a separate partial view for display. Clicking Edit pops open a model with a Form of EditorFor controls bound to the model properties for the selected item. When the submit button for the modal is clicked. It posts back the form for updating to the database...at which point I want to basically refresh the partial view that contains the dropdownlist so that it reflects the changes is appropriate.
The code I have performs all the basic mechanics without issue EXCEPT for refreshing the partial view that contains the dropdownlistfor control. I could just do a redirecttoaction for the index page and refresh the entire page but I would prefer to only refresh the partial view. I can not figure out how to make this happen and am wondering if someone has a suggestion.
The code div code for the index page is:
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<br />
<div class="partialContent" data-url="/Database/GetDatabases">
#Html.Partial("_GetDatabases")
</div>
<br />
<div class="modal fade" id="modalEditDBInfo" role="application" aria-labelledby="modalEditDBInfoLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modalEditDBInfoContent" style="background-color:white; border-radius:10px; box-shadow:10px;">
#Html.Partial("_EditDatabaseInfo")
</div>
</div>
</div>
The code for the EditDatabase partial view
#model Hybridinator.WebUI.Models.DatabaseModel
<br />
<br />
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<h4 class="modal-title" id="editModelTitle">Edit Database Info</h4>
</div>
#if(Model != null)
{
using (Html.BeginForm("EditDatabaseInfo", "Database", FormMethod.Post, new { #class = "modal-form" }))
{
<div class="modal-body">
#Html.HiddenFor(m => m.database_pk, new { htmlAttributes = new { #class = "form-control" } })
<div class="form-group">
<div id="databaselabel">#Html.LabelFor(m => m.database_name, "Database")</div>
<div id="databaseedit">#Html.EditorFor(m => m.database_name, new { htmlAttributes = new { #class = "form-control" } })</div>
</div>
<div class="form-group">
<div id="databaseserverlabel">#Html.LabelFor(m => m.database_server, "Database Server")</div>
<div id="databaseserveredit">#Html.EditorFor(m => m.database_server, new { htmlAttributes = new { #class = "form-control" } })</div>
</div>
</div>
<div class="form-group">
<div id="editsqltypelabel">#Html.LabelFor(m => m.sql_type_pk, "Sql Type")</div>
<div id="editsqltypeddl">#Html.DropDownListFor(m => m.sql_type_pk, Model.sqlTypes)</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button class="btn btn-inverse btn-primary" type="submit">Save</button>
</div>
}
}
The code for the GetDatabases partial view
#model Hybridinator.WebUI.Models.DatabaseListModel
#if(Model != null)
{
<div id="databasedropdown" class="container-fluid">
#Html.Label("Databases: ")#Html.DropDownListFor(m => m.database_pk, Model.databases, "Select one...", new { #id = "database_pk", onchange = "changeDatabase()" })
</div>
}
The Controller code for GetDatabases
public ActionResult GetDatabases()
{
DatabaseListModel databaseListModel = new DatabaseListModel
{
databases = databaseService.GetUndeletedDatabaseList().
Select(d => new SelectListItem
{
Value = d.database_pk.ToString(),
Text = d.database_name
}).ToList()
};
return PartialView("_GetDatabases",databaseListModel);
}
and last the code for both the Get and Post for the EditDatabase modal
[HttpGet]
public ActionResult EditDatabaseInfo(int database_pk)
{
DatabaseModel databaseModel = FillDatabaseModelByDatabasePK(database_pk);
return PartialView("_EditDatabaseInfo", databaseModel);
}
[HttpPost]
public ActionResult EditDatabaseInfo(DatabaseModel databaseModel)
{
string[] result = databaseService.Update(new Database
{
database_pk = databaseModel.database_pk,
database_name = databaseModel.database_name,
database_password = databaseModel.database_password,
database_username = databaseModel.database_username,
database_server = databaseModel.database_server,
hist_database_name = databaseModel.hist_database_name,
hist_database_server = databaseModel.hist_database_server,
hist_database_password = databaseModel.hist_database_password,
hist_database_username = databaseModel.hist_database_username,
sqlType = new SQLType { sql_type_pk = databaseModel.sql_type_pk }
});
return RedirectToAction("GetDatabases");
}
As I said the RedirectToAction("Index) returned in the Post EditDatabase controller method works in a pinch..but I really dont want to have to refresh the whole page. I assume there is something I can do differently in the return on that method to just reload the GetDatabases partial but I can't figure it out. Any help would be appreciated.
Carl who comments up above provided the solution. Buts since he just commented Ill post the code modifications here so if someone is looking for a similar issue they can see the code.
As per Carl's suggestion I used the Ajax.BeginForm rather than the HTML.BeginForm and IM updating the partial view controller through the onsuccess handler.
I replaced this line in the EditDatabase partial
using (Html.BeginForm("EditDatabaseInfo", "Database", FormMethod.Post, new { #class = "modal-form" }))
with this
using (Ajax.BeginForm("EditDatabaseInfo", "Database", new AjaxOptions{
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
OnSuccess = "editDatabaseSuccess"
}, new { #id = "editDatabaseForm" }))
Then in my scripts I made a function for the editDatabaseSucess
<script type="text/javascript">
function editDatabaseSuccess(data)
{
//alert(data);
$('#modalEditDBInfo').modal('hide');
loadDatabases();
}
</script>
The alert(data; commented out line was just for testing to make sure the function was being called.
the loadDatabases(); line calls the function I use on page load to load the partial view.
<script type="text/javascript">
function loadDatabases()
{
$(".partialContent").each(function (index, item) {
var url = $(item).data("url");
if (url && url.length > 0) {
$(item).load(url)
}
});
}
</script>
Works perfectly now. Much thanks to Carl for the answer.

MVC: On button click do some database action and stay on same view

In my view currently I have a form and inside those forms I have three other forms, child form is submitted, i want it to forward some method in controller that just performs some database action but then i want to stay on the same page after the database action is performed.
#using System.Web.Mvc.Html
#using System.Web.UI.WebControls
#using DatePicker.Models.ViewModels.Appointment
#model DatePicker.Models.ViewModels.Appointment.CreateAppointmentSelectPersons
#{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
<link href="~/Content/themes/base/minified/jquery-ui.min.css" rel="stylesheet"/>
}
<h2>Create</h2>
#using(Html.BeginForm("Create","Appointment", FormMethod.Post,new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<h4>Step 2</h4>
<hr />
#Html.ValidationSummary()
#*ChildForm1*#
using (Html.BeginForm("AddAttendeeManual", "Attendee"))
{
#Html.HiddenFor(m=>m.SelectedManualEmail.AppointmentId)
<div class="form-group">
#Html.LabelFor(m => m.SelectedManualEmail.Email, new { #class = "col-md-2 control-label" })
<div class="col-md-8 input-group">
#Html.TextBoxFor(m => m.SelectedManualEmail.Email, new { id = "Email", #class = "form-control",PlaceHolder="Email"}) <input type='submit' id="btnEmail" class="btn btn-default" value="Add>>" />
</div>
</div>
}
if (Model.IsSuperOfficeConnected)
{
#*ChildFrom2*#
using (Html.BeginForm("AddAttendeeSuperOffice","Attendee",FormMethod.Post))
{
#Html.HiddenFor(m => m.SelectedSuperOfficeEmail.FirstName, new { id = "SelectedSuperOfficeEmail_FirstName" })
#Html.HiddenFor(m => m.SelectedSuperOfficeEmail.LastName, new { id = "SelectedSuperOfficeEmail_LastName" })
#Html.HiddenFor(m=>m.SelectedSuperOfficeEmail.AppointmentId)
#Html.HiddenFor(m => m.SelectedSuperOfficeEmail.SuperOfficePersonId, new { id = "SelectedSuperOfficeEmail_SuperOfficePersonId" })
<div class="form-group">
#Html.LabelFor(m => m.SelectedSuperOfficeEmail.Email, new { #class = "col-md-2 control-label" })
<div class="col-md-8 input-group">
#Html.TextBoxFor(m => m.SelectedSuperOfficeEmail.Email, new { id = "SelectedSuperOfficeEmail", #class = "form-control", PlaceHolder = "Search in SuperOffice" })
<input type='submit' id="btnEmail" class="btn btn-default" value="Add>>" />
</div>
</div>
}
}
if (Model.IsInternalAddressBookEmpty)
{
#*ChildForm3*#
using (Html.BeginForm("AddAttendeeInternalAddressBook", "Attendee"))
{
#Html.HiddenFor(m=>m.SelectedAddressBookPerson.FirstName)
#Html.HiddenFor(m=>m.SelectedAddressBookPerson.LastName)
#Html.HiddenFor(m=>m.SelectedAddressBookPerson.AppointmentId)
<div class="form-group">
#Html.LabelFor(m => m.SelectedAddressBookPerson.Email, new { #class = "col-md-2 control-label" })
<div class="col-md-8 input-group">
#Html.TextBoxFor(m => m.SelectedAddressBookPerson.Email, new { id = "SelectedAddressBookPerson", #class = "form-control", PlaceHolder = "Search in AddressBook..." }) <input type='button' id="btnAddressBook" class="btn btn-default" value="Add>>">
</div>
</div>
}
}
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input class="btn btn-default" value="<<Previous"/>
<input type="submit" class="btn btn-default" value="Next>>" />
</div>
</div>
}
<style>
.ui-autocomplete-loading {
background: url('/Content/themes/base/images/ui-anim_basic_16x16.gif') no-repeat right center;
}
</style>
#section Scripts{
#Scripts.Render("~/bundles/jqueryval")
#Scripts.Render("~/Scripts/jquery-ui-1.10.4.min.js")
<script type="text/javascript">
$(function () {
$("#SelectedSuperOfficeEmail").
autocomplete({
source: '/Appointment/SuperOfficePerson',
minLength: 1,
select: function (event, ui) {
$('#SelectedSuperOfficeEmail').val(ui.item.value);
$(#Html.IdFor(m => m.SelectedSuperOfficeEmail.FirstName)).val(ui.item.FirstName);
$(#Html.IdFor(m => m.SelectedSuperOfficeEmail.LastName)).val(ui.item.LastName);
$(#Html.IdFor(m => m.SelectedSuperOfficeEmail.SuperOfficePersonId)).val(ui.item.ExternalPersonId);
}
});
$("#SelectedAddressBookPerson").autocomplete({
source: '/Appointment/AddressBookPerson',
minLength: 1,
select: function(event,ui) {
$(#Html.IdFor((m=>m.SelectedAddressBookPerson.FirstName))).val(ui.item.FirstName);
$(#Html.IdFor(m=>m.SelectedAddressBookPerson.LastName)).val(ui.item.LastName);
},
});
});
</script>
}
this is what i've done in controller
[HttpPost]
public void AddAttendeeSuperOffice(CreateAppointmentSelectPersons superOfficePerson)
{
_attendeeRepository.AddSuperOfficeAttende(superOfficePerson.SelectedSuperOfficeEmail.AppointmentId,
superOfficePerson.SelectedSuperOfficeEmail.FirstName,
superOfficePerson.SelectedSuperOfficeEmail.LastName,
superOfficePerson.SelectedSuperOfficeEmail.Email,
superOfficePerson.SelectedSuperOfficeEmail.SuperOfficePersonId);
}
[HttpPost]
public void AddAttendeeInternalAddressBook(CreateAppointmentSelectPersons internalAddressbookPerson)
{
_attendeeRepository.AddInternalAddressBookAttendee(
internalAddressbookPerson.SelectedAddressBookPerson.AppointmentId,
internalAddressbookPerson.SelectedAddressBookPerson.FirstName,
internalAddressbookPerson.SelectedAddressBookPerson.LastName,
internalAddressbookPerson.SelectedAddressBookPerson.Email);
}
[HttpPost]
public void AddAttendeeManual(CreateAppointmentSelectPersons manualEmail)
{
_attendeeRepository.AddManualAttendee(manualEmail.SelectedManualEmail.AppointmentId,
manualEmail.SelectedManualEmail.Email);
}
so whenever my childfrom gets submitted, database action takes place but I get forwarded to different link.
I could use, return RedirectToAction but I don't want to load the whole page again, thats makes it kind of slow to load whole thing again.
I thought of using Partial Views but then partial view didn't really help me achieve what I get.
Is there someway to just stay on the same page and make a void call upon child form submission, so that i stay on same page. Maybe, just make the textbox of the child form empty?
It is better to submit child forms to controller using Ajax.
Assuming the below child form you want to submit,
using (Html.BeginForm("AddAttendeeInternalAddressBook", "Attendee", new{id="frm-child-address"}))
then
$('#mybutton').click(function(){
var postData= $('#frm-child-address').serialize();
$.post('/Attendee/AddAttendeeInternalAddressBook',{data:postData},function(res){
//based on server response do whatever you require
});
});
You can use #Ajax.BeginForm and add a javascript callback that would fire off after the controller's action (database call) has completed.
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
#using (Ajax.BeginForm(new AjaxOptions { HttpMethod = "POST", OnSuccess = "done" }))
{
#* form *#
}
<script type="text/javascript">
function done(){
// The database call is complete.
}
</script>

Categories

Resources