I am using ajax.beginform to make an ajax login popup.
Everything works fine the first time, but when I submit a second time (after an error message from model validation) it no longer updates my div with the content but refreshes the page and shows the partial view in a blank page. It's not doing the ajax anymore.
I have included all javascripts needed.
My partial view:
#using (Ajax.BeginForm("Login", "Account", null, new AjaxOptions
{
UpdateTargetId = "login-partial-update",
HttpMethod = "POST",
OnSuccess = "loginSuccess"
}, new { id = "js-form-login" }))
{
<div class="fluid-row-margin">
<div class="cell12">
#Html.TextBoxFor(x => x.Email, new { placeholder = "Email address" })
<div class="errormessage">
#Html.ValidationMessageFor(x => x.Email)
</div>
</div>
</div>
<div class="fluid-row-margin">
<div class="cell12">
#Html.PasswordFor(x => x.Password, new { placeholder = "Password" })
<div class="cell12 errormessage">
#Html.ValidationMessageFor(x => x.Password)
</div>
</div>
</div>
<div class="fluid-row-margin">
<div class="cell1">
#Html.CheckBoxFor(x=>x.RememberMe)
</div>
<div class="cell11">Remember me</div>
</div>
<div class=" errormessage">
#if (Model.HasErrors)
{
<br />#Model.ErrorMessages
}
</div>
}
<script type="text/javascript">
$.validator.unobtrusive.parse("#js-form-login");
</script>
My parent view includes this partial
<div id="login-partial-update">
#Html.Partial("Widgets/Login/_LoginInput", new LoginInputModel())
</div>
All this is happening inside a javascript modal dialog
Related
first i create list of models in [HttpGet] action and return to view.
public ActionResult Setting()
{
var model = db.Settings.ToList();
return View(model);
}
them in view get list in view and show good.
but after edit the value of setting i want to pass list of object from view to controller don't work this.
#model List<TajerWebsite.Models.Setting>
<!-- Main content -->
<section class="content">
<div class="container-fluid">
<div class="row">
<!-- left column -->
<div class="col-md-6">
<!-- general form elements -->
<div class="card card-primary">
<div class="card-header">
<h3 class="card-title">تنظیمات</h3>
</div>
<!-- /.card-header -->
<!-- form start -->
#using (Html.BeginForm("Setting","Admin", new { FormMethod.Post }))
{
#Html.AntiForgeryToken()
foreach (var item in Model)
{
<div class="card-body">
<div class="form-group">
#Html.HiddenFor(model => item.Id)
<label for="exampleInputPassword1">#item.Name</label>
#Html.EditorFor(model => item.Value, new { htmlAttributes = new { #class = "form-control"} })
#Html.ValidationMessageFor(model => item.Value, "", new { #class = "text-danger" })
</div>
</div>
}
<!-- /.card-body -->
<div class="card-footer">
<button type="submit" class="btn btn-primary">ذخیره</button>
</div>
}
</div>
</div>
</div>
</div>
</section>
and action is :
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Setting(IEnumerable<Models.Setting> settings)
{
db.Entry(settings);
db.SaveChanges();
return View(settings);
}
but settings is null!
You can't use #foreach loop in the view in order to pass list of object back to the controller, because that would generate input elements with same IDs and Names.
Instead, use standard for loop:
for(int i = 0; i < Model.Count; i++)
{
<div class="card-body">
<div class="form-group">
#Html.HiddenFor(m => m[i].Id)
<label for="exampleInputPassword1">#Model[i].Name</label>
#Html.EditorFor(m => m[i].Value,
new { htmlAttributes = new { #class = "form-control"} })
#Html.ValidationMessageFor(m => m[i].Value,
new { #class = "text-danger" })
</div>
</div>
}
Layout -> View -> Partial View
In the View:
<div class="col-md-8">
#{Html.RenderPartial("_komentari", commentlist);}
<div class="gap gap-small"></div>
<div class="box bg-gray">
<h3>#Res.commentwrite_title</h3>
#using (Ajax.BeginForm("postcomment", new { propertyid = Model.PublicID }, new AjaxOptions { UpdateTargetId = "commentsarea", HttpMethod = "Post", InsertionMode = InsertionMode.Replace }, null))
{
<div class="row">
<div class="col-md-8">
<div class="form-group">
<label>#Res.commentwrite_content</label>
<textarea id="comment" name="comment" class="form-control" rows="6"></textarea>
</div>
<div class="form-group">
<input class="btn btn-primary" type="submit" value='#Res.commentwrite_btn' />
</div>
</div>
</div>
}
</div>
</div>
In the Partial View:
<div id="commentsarea">
<ul class="booking-item-reviews list">
#if (Model != null)
{
foreach (Comment item in Model)
{
<li>
<div class="row">
<div class="col-md-2">
<div class="booking-item-review-person">
<a class="booking-item-review-person-avatar round" href="#">
<img src="/assets/img/70x70.png" alt="Image Alternative text" title="Bubbles" />
</a>
<p class="booking-item-review-person-name">
#if (item.UserId != null)
{
<a href='#Url.Action("details", "user", new { userid = item.User.PublicId })'>#item.User.Username</a>
}
else
{
Anonymous
}
</p>
</div>
</div>
<div class="col-md-10">
<div class="booking-item-review-content">
<p>
#item.Content
</p>
<p class="text-small mt20">#item.DateOnMarket</p>
<p class="booking-item-review-rate">
#using (Ajax.BeginForm("reportcomment", new { comment = item.PublicId }, new AjaxOptions { UpdateTargetId = "reportscount", HttpMethod = "Post", InsertionMode = InsertionMode.Replace }, null))
{
<a id="submit_link" href="#">Spam?</a>
<a class="fa fa-thumbs-o-down box-icon-inline round" href="#"></a>
}
<b id="reportscount" class="text-color">#item.CommentReports.Count</b>
</p>
</div>
</div>
</div>
</li>
}
}
</ul>
</div>
<script>
$(function () {
$('a#submit_link').click(function () {
$(this).closest("form").submit();
});
});
</script>
View
Both scripts for Ajax are always included in the Layout (I'm already using Ajax on other pages too). On the View page, when I add a new comment, it is added in the database and shows the updated list of comments via ajax. Everything works fine.
Partial View
But if I want to report the comment as spam, I have to click on the link inside the Partial View (#submit_link), and after reporting, inside the #reportscount part, I want to show the updated number of reports of that comment. The actionresults returns that number like Content(numberofreports.toString()). It works but I get the number in a blank page?
Thank you very much.
It's better if you don't. The main issue is that, for security reasons, <script> tags are ignored, when HTML is inserted into the DOM. Since the Ajax.* family of helpers work by inserting <script> tags in place, when you return the partial via AJAX, those will not be present. It's better if you only include the HTML contents of the form in the partial, and not the form itself.
I have a page which has a list of Students. The partial view which renders a list is called "StudentManager". The partial view which I use in a modal to create a new student is called "NewStudent".
I have a couple of issues going on with this controller code. For some reason, after I press submit on the "NewStudent" partial view, every time afterwards that I refresh the page a new student is there without me going in and pressing submit... This is a problem.
Also, I have searched similar topics here on stack and I cannot seem to understand why return PartialView("StudentManager",db.Students.ToList()); will not automatically refresh my "StudentManager" view.
This code is supposed to give me a list in one partial view, and another partial view is supposed to let me create a new list item and then tell the list partial view to update.
Controller:
public ViewResult Index()
{
return View();
}
public ActionResult StudentManager()
{
return PartialView(db.Students.ToList());
}
public ActionResult NewStudent()
{
return PartialView();
}
//
// POST:
[HttpPost]
public ActionResult NewStudent(Student student)
{
if (ModelState.IsValid)
{
db.Students.Add(student);
db.SaveChanges();
return RedirectToAction("Index");
}
return PartialView();
}
Index.cshtml:
#Html.Action("StudentManager", "StudentController")
<div class="modal modal-wide fade" id="myModal4" role="dialog">
<div class="modal-dialog">
#Html.Action("NewStudent", "StudentController")
</div>
</div>
Here is the "NewStudent.cshtml" view:
#model GunneryTracker.Models.Student
<fieldset>
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<center>
<h4 class="modal-title">New Student</h4>
</center>
</div>
<div class="modal-body">
<div class="col-md-12">
<div class="clearfix"></div>
<div class="x_content">
<br />
<form class="form-horizontal form-label-left" >
<div class="form-group">
<div class="col-md-6 col-sm-6 col-xs-12">
<label class="control-label col-md-2 col-sm-2 col-xs-12" style="margin-right:10px">Course</label>
<div class="col-md-3 col-sm-3 col-xs-12">
#Html.DropDownList("CourseID", null, "-- Select Course --", htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.CourseID, "", new { #class = "text-danger" })
</div>
<label class="control-label col-md-2 col-sm-2 col-xs-12" style="margin-right:10px">Location</label>
<div class="col-md-3 col-sm-3 col-xs-12">
#Html.DropDownList("LocationID", null, "-- Select Location--", htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.LocationID, "", new { #class = "text-danger" })
</div>
</div>
<div class="editor-label">
#Html.LabelFor(model => model.FName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.FName)
#Html.ValidationMessageFor(model => model.FName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.LName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.LName)
#Html.ValidationMessageFor(model => model.LName)
</div>
</div>
<br />
<br />
<div class="form-group">
<center>
<p>
<input type="submit" value="Create" />
</p>
</center>
</div>
</form>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Save</button>
</div>
</div>
</fieldset>
Pardon the slouchy html... The prettyfication isnt completed...
Answer to 2nd question(if I understood what you meant):
It's not that smart as you expected.
After POST better to send back JSON result or simple null if don't use Ajax.
I would suggest you after POST do return RedirectToAction("Index");
Then page auto refresh students list.
Or do your POST via $.ajax and on success update student list using jquery or js
here is how I'm usually do it for simple "admin page" forms.
public ActionResult Teams()
{
var list = _data.GetTeams(true);
return View(list);
}
public ActionResult TeamCreate()
{
var model = _data.GetTeamCRUDViewModel();
return PartialView("_TeamCreate",model);
}
[HttpPost]
public ActionResult TeamCreate(TeamCRUDViewModel model)
{
_data.SaveTeam(model);
return RedirectToAction("Teams");
}
But on customer UI I would recommended to use $.ajax post.
Update:
Ok I see your issue
#model Student
<fieldset>
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">× </button>
<center>
<h4 class="modal-title">New Student</h4>
</center>
</div>
<div class="modal-body">
<div class="col-md-12">
<div class="clearfix"></div>
<div class="x_content">
<br />
#using (#Html.BeginForm("NewStudent", "Home", FormMethod.Post))
{
<div class="form-group">
<div class="col-md-6 col-sm-6 col-xs-12">
<label class="control-label col-md-2 col-sm-2 col-xs-12" style="margin-right: 10px">Course</label>
<div class="col-md-3 col-sm-3 col-xs-12">
#Html.DropDownList("CourseID", null, "-- Select Course --", htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.CourseID, "", new { #class = "text-danger" })
</div>
<label class="control-label col-md-2 col-sm-2 col-xs-12" style="margin-right: 10px">Location</label>
<div class="col-md-3 col-sm-3 col-xs-12">
#Html.DropDownList("LocationID", null, "-- Select Location--", htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.LocationID, "", new { #class = "text-danger" })
</div>
</div>
<div class="editor-label">
#Html.LabelFor(model => model.FName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.FName)
#Html.ValidationMessageFor(model => model.FName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.LName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.LName)
#Html.ValidationMessageFor(model => model.LName)
</div>
</div>
<br/>
<br/>
<div class="form-group">
<center>
<p>
<input type="submit" value="Create"/>
</p>
</center>
</div>
}
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Save</button>
</div>
</div>
Also change
#Html.Action("StudentManager", "StudentController") to #Html.Action("StudentManager", "Student")
like if should be name of controller
There's a fundamental misunderstanding here about how things work. A client makes a request to a server and the server returns a response. The client, then, generally does something with that response. In the case of a web browser, it clears the current view in the tab/window, parses the response and renders it into that tab/window. There's actually a lot more that goes on, but I'm trying to keep it simplistic.
However, AJAX (or specifically the XMLHttpRequest object in JavaScript) is what you would call a thin client. It's like a little web browser within your web browser, only without all the bells and whistles. All it does is submit requests and deliver the response to a callback. That callback is a JavaScript function whose job is to do something with the response. If the goal is to replace some portion of HTML on the page, the JavaScript code in the callback must do that. It does not happen automatically.
It's also important to realize that a "partial view" is only a thing server-side. Whether MVC is returning a partial view, a normal view, or even a view composed from various partial views is all inconsequential. What the server returns to the client is just an HTML document. In the case of the client being a web browser, it then parses that HTML document and builds what's called the Document Object Model, or DOM. It then uses the DOM to "render" the page as formatted images and text.
Likewise, all an AJAX request returns is an HTML document, which is itself really just a text document with a mime type of "text/html" that informs the client that it should be treated as HTML. As I said, it's the job of the AJAX callback to do something with this response from the server, but the point here is that you can't just say "replace that partial with this HTML", because the concept of partials doesn't exist client side. All you have is a object graph (the DOM), and you must select something from the DOM and then insert the HTML into that.
I have a view (refer below code) , but the datetimepicker is stretching , now to removed the stretching. May be this is due to the bootstrap table . Need some guide to display the datetimepicker in the elegant way.
<div class="container">
<div class="clearfix"></div>
#using (Html.BeginForm("Create", "DoctorPayment"))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
#*<legend>DoctorPayment</legend>*#
<div class="panel">
<div class="panel-body">
...
<div class="row">
<div class="col-lg-3 pull-left">
<div class="editor-label">
#Html.LabelFor(model => model.PaymentDate)
</div>
</div>
<div class="col-lg-9">
<div class="editor-field">
#Html.EditorFor(model => model.PaymentDate)
#Html.ValidationMessageFor(model => model.PaymentDate)
</div>
</div>
<div class="col-lg-1">
</div>
</div>
<div style="margin-top: 5px"></div>
....
</div>
<p>
<input type="submit" value="Create" />
</p>
</div>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
....
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
#Styles.Render("~/Content/boostrap")
#Scripts.Render("~/bundles/jqueryui")
#Styles.Render("~/Content/cssjqryUi")
<script type="text/javascript">
$(document).ready(function () {
$('input[type=datetime]').datepicker({
dateFormat: "dd/M/yy",
changeMonth: true,
changeYear: true,
yearRange: "-60:+0"
});
});
$('#PaymentDate').datepicker({
showButtonPanel: false,
beforeShow: function () {
$(".ui-datepicker").css('font-size', 12)
}
});
$("#PaymentDate").click(function () {
$("#ui-datepicker-div")
// BTW, min-width is better:
.css("min-width", $(this).outerWidth() + "px");
});
</script>
}
}
</div>
I have included bootstrap to it.
I believe that you might have overwritten something in css, or added some atributes.
Try this and see if it works.
$("#dropdown").closest("span.k-dropdown").width(400);
If it does, try to add a custom class to the datepicker so that you don't edit all dropdowns.
Also, changing the font size will change the size of the datepicker.
$('#PaymentDate').datepicker({
showButtonPanel: false,
beforeShow: function () {
$(".ui-datepicker").css('font-size', 12)
}
});
$("#PaymentDate").click(function () {
$("#ui-datepicker-div")
.css("max-width", $(this).outerWidth() + "px");
});
This question already has answers here:
MVC 3 - Html.EditorFor seems to cache old values after $.ajax call
(5 answers)
Closed 6 years ago.
I have a ASP MVC web app.
I have a partial form and it initally displays 'Hello Andy!'.
I press the submit button and I change this to 'Hello Andy Again!.
I pass the model back to the UI.
The label still shows the old value.
Why?
My markup:
#using (Ajax.BeginForm("SaveAlertPreferences", "Users", new AjaxOptions
{
UpdateTargetId = "partialform",
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
{
<div>
#Html.AntiForgeryToken()
<div class="section group">
<div class="col span_3_of_12">
#Html.LabelFor(model => model.myStub)
</div>
<div class="col span_9_of_12">
#Html.TextBoxFor(model => model.myStub)
</div>
</div>
<div class="section group">
<div class="col span_3_of_12">
</div>
<div class="col span_4_of_12">
<input type="submit" value="Press me" />
</div>
<div class="col span_5_of_12">
</div>
</div>
</div>
}
My Model:
public class ChangeAlertPreferencesModel
{
public string myStub { get; set; }
}
My Controller:
[AcceptVerbs("HEAD", "GET")]
public PartialViewResult _ChangeAlertPreferences()
{
Response.CacheControl = "no-cache";
ChangeAlertPreferencesModel m = new ChangeAlertPreferencesModel();
m.myStub = "Hello Andy!";
return PartialView("_ChangeAlertPreferences", m);
}
[HttpPost]
public PartialViewResult SaveAlertPreferences(ChangeAlertPreferencesModel m)
{
Response.CacheControl = "no-cache";
if (ModelState.IsValid)
{
m.myStub = "Hello Andy Again!";
return PartialView("_ChangeAlertPreferences", m);
}
else
{
m.myStub = "I have errored!";
return PartialView("_ChangeAlertPreferences", m);
}
return null;
}
To complete my comment, your form statement looks odd,so you might wanna try this:
#using (Ajax.BeginForm("SaveAlertPreferences", "Users", new AjaxOptions
{
UpdateTargetId = "partialform",
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
}))
{
#Html.AntiForgeryToken()
<div class="section group">
<div class="col span_3_of_12">
#Html.LabelFor(model => model.myStub)
</div>
<div class="col span_9_of_12">
#Html.TextBoxFor(model => model.myStub)
</div>
</div>
<div class="section group">
<div class="col span_3_of_12">
</div>
<div class="col span_4_of_12">
<input type="submit" value="Press me" />
</div>
<div class="col span_5_of_12">
</div>
</div>
}
To explain, in the first line, the using part declares the form and how it should behave, then you end(close) that declaration and open the block that should contain the body of the form.