I have a view that is used for editing stuff, say Orders. Orders have line items that can be added arbitrarily. So a main view and nested partialviews.
Each partial should have an ajax form for tweaking quantities of each line item or whatever.
Thus:
Html.BeginForm()
{%>
Ship to: blah blah blah
<%
Ajax.BeginForm("EditLineItem", "Order", new { OrderLineItemID = Model.ObjectID }, itemAjaxOptions))
{
Item qty blah blah blah
<--! (ajax form's submit button, etc.)-->
}
%>
<--! (ajax form's submit button, etc.)-->
<%
}
I have a controller that looks like this:
[ActionName("Edit")]
[AcceptVerbs(HttpVerbs.Post)]
[ValidateAntiForgeryToken]
public ActionResult Edit(int orderID)
{
blah, blah
}
[ActionName("EditLineItem")]
[AcceptVerbs(HttpVerbs.Post)]
[ValidateAntiForgeryToken]
public ActionResult EditLineItem(Guid orderLineItemID)
{
blah, blah
}
My trouble is that when I submit the Ajax form, I get the Edit method instead of the EditLineItem methods. Both routes are mapped. Is there some gotcha like "you can't submit an Ajax form inside of an Html form" that I don't know about?
I tried the exact same thing a while ago. No matter what I did, it wouldn't do the AJAX submit. So I think the answer is: yes, you can't put a submit button for an AJAX form inside a regular html form.
But, why would you have partial submits merged with full submits?
The easiest workaround to this imo would be to use JSON requests with jQuery.
for instance, updating a quantity span text when you change a dropdownlist (id=Order):
<script type="text/javascript">
$(document).ready(function() {
$('select#Order').change(function() {
$.getJSON('/Orders/UpdateQty/' + this.value, {},
function(data) {
$('#qty').html(data);
});
});
});
</script>
And the code in the "Orders" controller:
public class OrdersController : Controller
{
public ActionResult UpdateQty(int id)
{
return Json(yourLibrary.getQuantities(id));
}
}
This Link might help.
Regards
Edit:
So.. the link no longer exists. But thanks to the internet wayback machine, we have this copy :)
AFAIA the AjaxForm is still renders as a form tag, so you'd be nesting forms, which as you've found is a no no.
I reckon Francisco is on the right lines (tho I'd suggest implementing a post rather than a get as you are updating something).
Kind regards,
TP
Related
This is a follow on to similar question but taking suggestions into account.
Render part of page on dropdown selection
I have a chart on my main view which I would like to update partially when a dropdown selects different values.
The page renders correctly the first time, but when I select a new value in the dropdown, then I think the .submit script is failing in the script .submit() because when I put a break on window.submitAjaxForm it is never reached.
_PnlChart.cshtml
<img src="#Url.Action("CreateTraderPnlChart3")" width="600" height="600" align="middle" vspace="50" />
My mainview Index.cshtml:
<div class="w3-half">
<div id="ExportDiv">
#{ Html.RenderPartial("_PnlChart");}
</div>
#using (Ajax.BeginForm("GetEnvironment",
new RouteValueDictionary { { "Environment", "" } }, new AjaxOptions() { UpdateTargetId = "ExportDiv" }, new { id = "ajaxForm" } ))
{
#Html.DropDownList("PeriodSelection",
new SelectList((string[])Session["Periods"]),
(string)Session["Period"],
new
{ onchange = "submitAjaxForm()" })
}
</script>
<script type="text/javascript">
$('form#ajaxForm').submit(function(event) {
eval($(this).attr('onsubmit')); return false;
});
window.submitAjaxForm = function(){
$('form#ajaxForm').submit();
}
</script>
</div>
My controller:
public ActionResult PeriodSelection(string dropdownlistReturnValue) // dont know what dropdownlistReturnValue is doing?
{
Session["Period"] = dropdownlistReturnValue;
return PartialView("~/Views/Employee/_PnlChart.cshtml");
}
This line in your code,
eval($(this).attr('onsubmit')); return false;
I am not sure what you were intending to do here. But from your question, i assume you wanted to do a form submission. But that line will not submit the form. The expression $(this).attr('onsubmit') is going to return undefined as your form does not have an onsubmit attribute defined.
But you already have the form submit code in your other method (submitAjaxForm). So if you simply remove the $('form#ajaxForm').submit handler (apparently it does not do anything useful), your code will work. When you change the dropdown, it will make an ajax form submission.
But your form action is set to GetEnvironment action method. That means your ajax form submission will be to that action method. In your question you have a different action method which returns the updated chart content. It does not makes sense!
I personally prefer to write handwritten ajax calls instead of relying on the ajax action helper methods. The below is the code i would probably use (Except the dropdownlist code. read further)
<div id="ExportDiv">
#{ Html.RenderPartial("_PnlChart");}
</div>
#Html.DropDownList("PeriodSelection",
new SelectList((string[])Session["Periods"]),
(string)Session["Period"], new
{ data_charturl = Url.Action("PeriodSelection","Home")})
Now listen to the change event of the SELECT element.
$(function(){
$("#PeriodSelection").change(function(){
var v = $(this).val();
var url=$(this).data("charturl")+'?dropdownlistReturnValue='+v;
$("#ExportDiv").load(url);
});
});
You should consider using the a view model to pass the Dropdownlist data. Why not use the DropDownListFor helper method ? It looks much clean, Mixing a lot of C# code (See all the session casting and all.) makes it kind of dirty IMHO.
I'm trying to make a HTML table with a checkbox column where this checkbox column is from a ViewModel:
public string FirstName ...
public string LastName ...
public bool Checked ...
I want to get the List<ViewModel> and pass it to the controller, using a Partial View, to verify the checked columns, because I want to delete the checked lines.
If I wanted to get the checked columns in the same controller, I do, but in a different controller, I don't. In my case, this 'Partial View' is a BS Modal.
What you need is a partial rendered through Ajax. You call the action method from a modal using load and POST the form data so it removes checked lines. You can call any controller you need from this, all you need is:
$('#target').load('#Html.Url("Action", "Controller")');
And on submit:
$('#targetform').submit(function (e) {
var data = JSON.stringify($(e.currentTarget).serialize());
$.post('#Html.Url("Action", "Controller")', data, function (html) {
$('#target').html(html);
});
e.preventDefault();
});
I want to display the details of particular record on same page, user can choose the product from the list of Product name and as soon as user clicks on the links the details of the specific product should display on the other side of the page i.e. othe div. I tried it by creating partial View and Ajax but the details are not displayed on the separate page a new blank page is opened with the name of Partialview and the records are displayed there, but i want details on the same page.ProductName are comming from database, first time the page loads it must contains the details of first record by default, that is working OK. Please try to solve this problem. Thanks
HomeController.cs
public class HomeComtroller:Controller
{
dbProductEntity Productdbentity=new dbProductEntity();
public ActionResult ProductDetails(int id)
{
var query=Productdbentity.tbl_product.First(c=>c.ProductId==id);
return PartialView("PartialView",query);
}
public ActionResult Product()
{
return View(dbentity.tbl_product.ToList());
}
PartialView.cshtml
#model MvcProject.Models.tbl_product
<label> #Model.ProductName </label>
<label> #Model.ProductDesc </label>
Product Page
#model List<MvcProject.Models.tbl_product>
<html>
<head>
<script type="text/javascript">
$(document).ready(function(){
$(div.product a").click(function(e){
var url=this.ref;
$get(url,{},function(data) {
$('#product-detail').html(data);
});
});
});
</script>
</head>
<body>
<div class="product">
<ul class="list">
#foreach(var item in Model)
{
<li><a href="#Url.Action("ProductDetail","Home",new {id=item.ProductId})">
#item.ProductName</a></li>
}
</ul>
<div class="product-detail">
#{Html.RendererPartial("PartialView",Model.FirstOrDefault());}
</div>
</div>
</body>
</html>
You should cancel the default action of the anchor by returning false from your .click event handler:
$(document).ready(function() {
$(div.product a").click(function(e) {
var url=this.ref;
$get(url,{},function(data) {
$('#product-detail').html(data);
});
});
return false; // <-- That's the important bit you were missing
});
If you do not return false from the .click handler, the browser will simply follow the linking to which your anchor is pointing stopping any javascript execution you might have started. Returning false ensures that the browser will not redirect away from the current page, leaving you the possibility to execute an AJAX request and update the current view.
I think you are missing "." after the "$" in first line in below code. And in second line, since "product-detail" is a class name so in jQuery selector use "." (not "#") before class name. Below is the corrected code:
$.get(url,{},function(data) {
$('.product-detail').html(data);
});
For more have a look at http://api.jquery.com/jQuery.get/
You have to stop the default behavior of click event on a link.
<script>
$(function(){
$("div.product a").click(function(e){
e.preventDefault();
var url=this.ref;
$('.product-detail').load(url);
});
});
</script>
I am developing an ASP .Net MVC 3 application using C# and SQL Server 2005.
I am using also Entity Framework and Code First Method.
In a view Index, I have a DropDownList Gamme. I define its item selected in my view, like this :
public string SelectedProfile_Ga { get; set; }
In this view, I have a button Appliquerthat took me to another view Application.
<input type="button" value="Appliquer" id="appliquer" onclick="window.location = 'ProfileGa/Application'"/>
In the view Application, I have a button submit Appliquer.
<input type="submit" value="Appliquer" id="appl" />
When I click on Appliquer, I want save the value selected in my DropDownList Gamme in my base.
The problem is that this value is passed NULL when i change the view (exit page Index and open Application).
I find that with Debugging.
The Controller action :
[HttpPost]
public ActionResult app(FlowViewModel model)
{
Famille fam = new Famille();
fam.ID_Gamme = model.SelectedProfile_Ga;
db.Familles.Add(fam);
db.SaveChanges();
return RedirectToAction("Application");
}
Note :
I didn't forget this in the Application:
<% using (Html.BeginForm("app", "ProfileGa")) { %>
ProfileGa is the name of my controller.
For starters, your dropdown is in the Index view, and the selection is happening there. Then you're redirecting to ProfileGa/Application and leaving this information behind.
I would change this button:
<input type="button" value="Appliquer" .. etc
to a <submit>, and wrap the code with the dropdown in one of these:
using (Html.BeginForm("Application", "ProfileGa")) {
and add a Post version of Application
[HttpPost]
public ActionResult Application(FlowViewModel model)
{
// Do whatever
return View(model);
}
Then when you get to the Application view, it should still have the same information as it left Index with.
To check this is working, put a breakpoint at return View(model); and look at the model's contents.
However, posting null from the view probably means that something is wrong inside your <% using (Html.BeginForm("app", "ProfileGa")) { %> statement, so if the above doesn't do anything, post the code from your `Application' view.
i have a textbox with button search.
i would like to search my database of input text from textbox and give result out in one view.
Could you please give me link or help me how its possible to implement?
I have no idea what i shoul to do that.
If you want to show the result in the same view page as that of the search criteria text box, the better approach will be to go with JQuery form post. And from the corresponding controller you can get back the JSON result and bind it to the grid, if you are using any third party grid.
The posting mechanism will be :
<div>
<input type="text" id="txtSearchText" value=""/>
<input type="button" id="btnSearch" value="Search"/>
</div>
<script type="text/javascript">
$("#btnSearch").click(function(){
var formPost={ SearchText : $("#txtSearchText").val()};
//The above SearchText parameter name should be same as property name in the Model class.
$.post("/SearchController/Search",formPost,function(data){
if(data)
{
//Here based on your development methodology, either build a table by
//appending a row for each result Or bind to a grid, if you are using
//any third party control
}
});
});
</script>
Controller Code :
public class SearchController
{
public ActionMethod Search(SearchModel searchCriteria)
{
SearchResultModel result= //Get the search results from database
return new JsonResult{Data=result};
}
}
Model class:
public class SearchModel
{
public string SearchText{get;set;};
}