I`m trying to send a form in mvc with Ajax.beginform and execute on success function. The function is stated in the form and created in the scripts section. However, the function is not fired after the post is submitted.
The view is partial view and is inserted in Index page.
The method which the form calls in the controller is HttpPost and returns the view again which causes the index page to load again.( I suspect here is the problem)
Basically what im trying to achieve is to show a div in my index page(main) saying successfully record edited.
Also, in my bundle config I have the jquery val & the jquery.validate.unobtrusive.js loaded and in the web.config I added in appconfig
What could be wrong? Here is my code.
[HttpPost]
public async Task<ActionResult> EditPostedJob(JobPost job, string dt)
{
using (var context = new ApplicationDbContext())
{
var post = (from p in context.jobPosts where p.JobPostId == job.JobPostId select p).First();
post.AboutJob = job.AboutJob;
post.Headline = job.Headline;
post.JobAddress = job.JobAddress;
post.JobCity = job.JobCity;
post.JobPostCode = job.JobPostCode;
await context.SaveChangesAsync();
//return Json(post,JsonRequestBehavior.AllowGet);
return RedirectToAction("Index", "Manage");
}
}
in my main view I have this message
<div id="success-edited-job" class="alert alert-success">
<strong>Success!</strong> the posted job has been successfully edited.
</div>
and also I have the js which hides this when page is loaded. And then I add the partial view with the form and there is set the success-edited-job div to show when post is successful but it return again the index view and the div is hidden again.
this is my partialview form
#using (Ajax.BeginForm("EditPostedJob", FormMethod.Post, new AjaxOptions() { OnSuccess = "JobEditedSuccessfully", OnFailure = "JobEditFail",HttpMethod="POST" }))
and the js
<script type="text/javascript">
function JobEditedSuccessfully(data) {
alert("lol");
}
function JobEditFail(error) {
console.error(error);
}
</script>
Related
I want to show a success message after calling the following ajax.beginform
from Index view
#using (Ajax.BeginForm("Insert", "Home", new AjaxOptions() { UpdateTargetId = "result", HttpMethod = "POST" }))
{
#Html.TextAreaFor(m => m.openion)
}
this is my result div
<div id="result">
</div>
and my controller is
[Httppost]
public ActionResult InforMessage(openionModel usr)
{
return Content("Thanks for adding your openion");
}
but when i try this it is going to another view InforMessage
It is not updating the result div.
There is no Informessage Exist. Still it open a new page with message
"Thanks for adding your openion".How to solve this?
If your redirecting to another page its because you do not have the correct scripts loaded (or have duplicates or have them in the wrong order) so its doing a normal submit.
Ensure you have included (in order)
jquery-{version}.js
jquery.unobtrusive-ajax.js
I have a form in which I need to call two action methods, one after the other. This is how the flow goes.
First I check if the prerequisite data is entered by the user. If not then I show a message that user needs to enter the data first.
If all the prerequisite data is entered, I call an action method which return data. If there is no data returned then I show a message "No data found" on the same page.
If data is returned then I call another action method present in a different controller, which returns a view with all the data, in a new tab.
The View:
#using (Ajax.BeginForm("Index", "OrderListItems", null, new AjaxOptions { OnBegin = "verifyRequiredData"}, new { #id = "formCreateOrderListReport", #target = "_blank" }))
{
//Contains controls and a button
}
The Script in this View:
function verifyRequiredData() {
if ($("#dtScheduledDate").val() == "") {
$('#dvValidationSummary').html("");
var errorMessage = "";
errorMessage = "<span>Please correct the following errors:</span><ul>";
errorMessage += "<li>Please enter Scheduled date</li>";
$('#dvValidationSummary').append(errorMessage);
$('#dvValidationSummary').removeClass('validation-summary-valid').addClass('validation-summary-errors');
return false;
}
else {
$('#dvValidationSummary').addClass('validation-summary-valid').removeClass('validation-summary-errors');
$('#dvValidationSummary').html("");
$.ajax({
type: "GET",
url: '#Url.Action("GetOrderListReport", "OrderList")',
data: {
ScheduledDate: $("#dtScheduledDate").val(),
Crews: $('#selAddCrewMembers').val(),
Priorities: $('#selPriority').val(),
ServiceTypes: $('#selServiceTypes').val(),
IsMeterInfoRequired: $('#chkPrintMeterInfo').val()
},
cache: false,
success: function (data) {
debugger;
if (data !== "No data found") {
//var newUrl = '#Url.Action("Index", "OrderListItems")';
//window.open(newUrl, '_blank');
return true;
} else {
//Show message "No data found"
return false;
}
}
});
return false;
}
}
The "GetOrderListReport" Action method in "OrderList" Controller:
public ActionResult GetOrderListReport(OrderListModel model)
{
var contract = new OrderReportDrilldownParamDataContract
{
ScheduledDate = model.ScheduledDate
//Setting other properties as well
};
var result = OrderDataModel.GetOrderList(contract);
if (string.IsNullOrWhiteSpace(result) || string.IsNullOrEmpty(result))
{
return Json("No data found", JsonRequestBehavior.AllowGet);
}
var deserializedData = SO.Core.ExtensionMethods.DeserializeObjectFromJson<OrderReportDrilldownDataContract>(result);
// send it to index method for list
TempData["DataContract"] = deserializedData;
return Json(deserializedData, JsonRequestBehavior.AllowGet);
}
The last action method present in OrderListItems Controller, the result of which needs to be shown in a new tab:
public ActionResult Index()
{
var deserializedData = TempData["DataContract"] as OrderReportDrilldownDataContract;
var model = new OrderListItemViewModel(deserializedData);
return View(model);
}
The problem is that I am not seeing this data in a new tab, although I have used #target = "_blank" in the Ajax.BeginForm. I have also tried to use window.open(newUrl, '_blank') as can be seen above. But still the result is not shown in a new tab.
Please assist as to where I am going wrong?
If you are using the Ajax.BeginForm you shouldn't also be doing an ajax post, as the unobtrusive ajax library will automatically perform an ajax post when submitting the form.
Also, if you use a view model with data annotation validations and client unobtrusive validations, then there would be no need for you to manually validate the data in the begin ajax callback as the form won't be submitted if any validation errors are found.
The only javascript code you need to add in this scenario is a piece of code for the ajax success callback. That will look as the one you currently have, but you need to take into account that opening in new tabs depends on the browser and user settings. It may even be considered as a pop-up by the browser and blocked, requiring the user intervention to allow them as in IE8. You can give it a try on this fiddle.
So this would be your model:
public class OrderListModel
{
[Required]
public DateTime ScheduledDate { get; set; }
//the other properties of the OrderListModel
}
The form will be posted using unobtrusive Ajax to the GetOrderListReport of the OrderList controller. On the sucess callback you will check for the response and when it is different from "No data found", you will then manually open the OrderListItems page on a new tab.
This would be your view:
#model someNamespace.OrderListModel
<script type="text/javascript">
function ViewOrderListItems(data){
debugger;
if (data !== "No data found") {
var newUrl = '#Url.Action("Index", "OrderListItems")';
//this will work or not depending on browser and user settings.
//passing _newtab may work in Firefox too.
window.open(newUrl, '_blank');
} else {
//Show message "No data found" somewhere in the current page
}
}
</script>
#using (Ajax.BeginForm("GetOrderListReport", "OrderList", null,
new AjaxOptions { OnSucces= "ViewOrderListItems"},
new { #id = "formCreateOrderListReport" }))
{
#Html.ValidationSummary(false)
//input and submit buttons
//for inputs, make sure to use the helpers like #Html.TextBoxFor(), #Html.CheckBoxFor(), etc
//so the unobtrusive validation attributes are added to your input elements.
//You may consider using #Html.ValidationMessageFor() so error messages are displayed next to the inputs instead in the validation summary
//Example:
<div>
#Html.LabelFor(m => m.ScheduledDate)
</div>
<div>
#Html.TextBoxFor(m => m.ScheduledDate, new {id = "dtScheduledDate"})
#Html.ValidationMessageFor(m => m.ScheduledDate)
</div>
<input type="submit" value="Get Report" />
}
With this in place, you should be able to post the data in the initial page using ajax. Then based on the response received you will open another window\tab (as mentioned, depending on browser and user settings this may be opened in a new window or even be blocked) with the second page content (OrderListItems).
Here's a skeleton of what I think you are trying to do. Note that window.open is a popup though and most user will have popups blocked.
<form id="formCreateOrderListReport">
<input type="text" vaule="testing" name="id" id="id"/>
<input type="submit" value="submit" />
</form>
<script type="text/javascript">
$('#formCreateOrderListReport').on('submit', function (event) {
$.ajax({
type: "POST",
url: '/home/test',
data: { id: $('#id').val()},
cache: false
}).done(function () {
debugger;
alert("success");
var newUrl = '/home/contact';
window.open(newUrl, '_blank');
}).fail(function () {
debugger;
alert("error");
});
return false;
});
</script>
Scale down the app to get the UI flow that you want then work with data.
I have a form with some controls. There is a button on the form which loads a partial view. Inside the partial view, there are two required field textboxes along with a button. And when its clicked, I need to display error messages only for textboxes which are inside the partial view, but not for the fields in the actual form. And when I click form's submit button, all error messages must show up.
After partial view is loaded, I am re-initializing the validation plugin as below.
$('#test').removeData("validator");
$.validator.unobtrusive.parse('#test');
I tried using validation attribute described in below thread but its not working. Maybe it works for normally loaded views.
ASP.NET MVC Validation Groups?
However, I can validate individually by calling textbox1.valid() and textbox2.valid(). But I think I am missing standard way of doing it. Any help is appreciated.
you can do this by submitting your partial view using Ajax.BeginForm()
//In Partail View
#model SomeModel
#using (Ajax.BeginForm("SomeActionName", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "targetId"}))
{
#Html.EditorFor(mode=>model.FirstText)
#Html.EditorFor(mode=>model.SecText)
<input type="submit" value="save">
}
//In Controller
public ActionResult SomeAction(SomeModel model)
{
return PartaiulView(model);
}
here you can validate your Partial View
NOTE: when you submit you form using Ajax.BeginForm you must specify "UpdateTargetId" where your result will be appear on View.
//In View
<div id="targetId">
#Html.Partail("PartialView")
</div>
OR if you want to Redirect to another action if your model is valid then modified your action
public ActionResult SomeAction(SomeModel model)
{
if(ModelState.IsValid)
{
return Json(new {redirect = #Url.Action("SomeAction","SomeController")})
}
return PartaiulView(model);
}
then in partail view you can invoke OnSuccess method of Ajax.BeginForm
#using (Ajax.BeginForm("SomeActionName", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "targetId",OnSuccess="success"}))
{
}
<script type="text/javascript">
function success(data)
{
if(data.redirect)
{
windows.location = data;
}
}
</script>
check both way which one is suitable to you.
I've got a page that contains multiple links. These links should do an ajax post and callback. However, the link is doing a Get instead of a Post. This causes a 404 error since I do not have an action method to handle a get at the requested URL.
If I remove the HTTPPost attribute from my Action method, the link works, but the call back fails and the Json I return is rendered in a new page.
Here is the code I'm using in my view.
<td id="action-#item.ItemID">#Ajax.ActionLink("Add", "AddToOrder", new { itemID = item.ItemID }, new AjaxOptions { HttpMethod = "POST", OnSuccess = "actionCompleted" }, new { id = "add-" + item.ItemID })</td>
This ends up adding this HTML:
<td id="action-012679"><a data-ajax="true" data-ajax-method="POST" data-ajax-success="actionCompleted" href="/mysite/neworder/AddToOrder?itemID=012679" id="add-012679">Add to Order</a></td>
My Controller has the following Action Method.
[HttpPost]
public JsonResult AddToOrder(string itemID) {
return Json(new { id = itemID, Action = "Added", "Just getting this working"});
}
My callback method that is called on Success looks like this:
<script language="javascript" type="text/javascript">
function actionCompleted(response, status, data) {
alert("We have returned");
}
</script>
If I change the [HTTPPost] attribute on my action method to [HTTPGet] I get an Json error. I can fix this by adding the JsonRequestBehavior.AllowGet to my return value, but this doesn't use the call back function defined on the page and fails.
Any help would be appreciated.
Probably you don't have jquery.unobtrusive-ajax.js script attached to page and link is gracefully degraded to regular anchor.
In order to have this working properly. You need to add references to these scripts on your page:
MicrosoftAjax.js
MicrosoftMvcAjax.js
I have a form which loads within a fancybox so that if the user clicks on a link, a form loads up in fancybox, its an #Ajax.BeginForm(). Like so:
#using (Ajax.BeginForm("AddToBasket", new { controller = "Orders" }, new AjaxOptions()
{
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "SuccessBasket",
OnSuccess = "goToCheckout"
}, new { #class = "product-order-form" }))
{
#* Form elements for Model *#
<div id="SuccessBasket"></div>
}
This gets loaded up in a fancybox window. When I submit the form, my SuccessBasket div does not get updated with the new content passed from the controller, is there some way to enable Ajax calls to be updated within Fancybox? This works fine if I don't use fancybox but I wish to use it.
EDIT:
The form is loaded like so:
#Ajax.ActionLink("Order", "OrderProduct", new { controller = "Orders", id = ViewData["ID"], search = ViewData["search"] }, new AjaxOptions()
{
UpdateTargetId = "ModalWindow",
InsertionMode = InsertionMode.Replace,
OnFailure = "NotAuthorised"
}, new { #class = "lightbox order-link" })
I have an empty div called ModalWindow which is wrapped by a div set to display: none as per the instructions:
<div style="display: none">
<div id="ModalWindow">
</div>
</div>
OrderProduct Action in my controller returns a PartialView:
return PartialView("_OrderProduct", basket);
Where basket is my model BasketModel basket = new BasketModel();
My _OrderProduct PartialView is the view which contains the Ajax form at the start of my post. Which has the SuccessBasket div.
Upto this point, it works perfectly. The form loads up in fancybox.
The AddToBasket Action returns a PartialView:
return PartialView("_BasketSuccess");
This view simply tells the user that their item was added to the basket:
<p>This item has been added to your basket. Search again or goto #Html.ActionLink("checkout", "Order", new { controller = "Orders" }, new { #class = "checkout-link" }) to continue.</p>
The problem is, the SuccessBasket div does not update with the text above but through debugging, I can see that it does load the view _BasketSuccess, it just doesn't update in the modal window.
The way you are loading the fancybox is strange. You are sending 2 AJAX requests: one for the Ajax.ActionLink and one by the fancybox. All that is not necessary. Also you don't need a hidden div in your main view, the fancybox does all this automatically.
So to recap, in your main view all you need is a simple HTML link to the controller actin which will return a partial containing the form:
#Html.ActionLink("Order", "OrderProduct", "Orders", null, new { #class = "lightbox" })
and in a separate javascript file you will attach the fancybox to this anchor so that when it is clicked it will automatically send an AJAX request (the fancybox, not you), fetch the partial form and show it:
$(function () {
$('.lightbox').fancybox();
});
Alright, now you have a partial form shown in a fancybox. This partial form is actually an Ajax.BeginForm. So when you submit this form it will send an AJAX request to the AddToBasket action and upon success it will update the <div id="SuccessBasket"></div> which is inside this form with the result returned by this action.