How can I put data attributes within an Ajax.BeginForm? - asp.net-mvc

Because I am using Knockout in my view, I have set my form tag accordingly;
<form class="employeeListEditor" data-bind="submit: save">
However when I click the submit button, I want to do a partial page refresh. So how do I set the data-bind attribute in the Ajax.BeginForm?
This syntax does not work;
<% using (Ajax.BeginForm("GetCalendar", new AjaxOptions { UpdateTargetId = "siteRows" }, new { data-bind="submit: save", class="employeeListEditor" }))
{%>

You need to use unserscore (_) in your attribute name and the Ajax.BeginForm helper (in fact all the HTML helpers replaces unserscore with dashes in the given htmlAttributes object parameters) will be automatically replace it with a dash (-)
new { data_bind="submit: save", #class="employeeListEditor" }
And you need use an Ajax.BeginForm overload which accepts htmlAttributes like this one:
<% using (Ajax.BeginForm(
"GetCalendar", // actionName
null, // routeValues
new AjaxOptions { UpdateTargetId = "siteRows" }, // ajaxOptions
new { data_bind="submit: save", #class="employeeListEditor" } // htmlAttributes
))
{%>

Related

MVC4 PartialViews without returning

Main view contains #Ajax.ActionLink links that updates a div target with partialViews. All works fine.
#Ajax.ActionLink("Update", "MemberInfo", new AjaxOptions() { HttpMethod = "GET", UpdateTargetId = "divCurrentView", InsertionMode = InsertionMode.Replace })
<div id="divCurrentView"></div>
Question is: When displaying a partialview and on click currently I update data and return to the same partial view that reloads the data. also reloads dropdownlists..etc `
Calling Partial View:
public PartialViewResult MemberInfo(){
.......
ViewBag.Members= new SelectList(_db.Members, "Id", "Text");
return PartialView("_MemberInfo",model);
}
[HttpPost]
public PartialViewResult MemberInfo(InformationVM model){
....... update data
//if I dont include the ViewBag again it will fail on reload
ViewBag.Members= new SelectList(_db.Members, "Id", "Text");
return PartialView("_MemberInfo",model);
}
instead of return to the same PartialView can I just show a message on the screen "data was updated" within the partial view.?
When you define your ActionLink, you can choose the element that gets replaced:
#Ajax.ActionLink("Do something", "_Methodname", new AjaxOptions {
HttpMethod = "POST",
UpdateTargetId = "StatusMessage",
InsertionMode = InsertionMode.Replace,
}, new {#class = "text-danger"})
<span id="StatusMessage"></span>
This way, the message gets loaded into the span element.
In that case, I'd include the actionlink inside the div and replace the content of the div (including the actionlink) with the partial, this time including another (different) actionlink.
<div id="divCurrentView">
#Ajax.ActionLink("Update", "MemberInfo", new AjaxOptions() { HttpMethod = "GET", UpdateTargetId = "divCurrentView", InsertionMode = InsertionMode.Replace })
</div>
Partial:
<div id="divCurrentView">
#Ajax.ActionLink("Update", "MemberInfo", new AjaxOptions {
HttpMethod = "POST", UpdateTargetId = "StatusMessage", InsertionMode = InsertionMode.Replace})
<span id="StatusMessage"></span>
</div>
That way, the second (and subsequent) clicks will POST and use the different method in the controller.

ViewModel not storing values when Ajax.ActionLink calling controller

When I'm clicking ActionLink and setting ViewModel values in controller I can see changes when View being rendered. But same values comes as null into Controller when I'm clicking ActionLink second time.
How do I store the value, so it comes into controller ?
View:
#Ajax.ActionLink("Click me", "AjaxTest", "Controller", new AjaxOptions()
{
UpdateTargetId = "updatePanel",
HttpMethod = "POST",
OnSuccess = "A()"
})
<div id="updatePanel">
#Html.Partial("~/Views/Shared/_UpdatableContent.cshtml", this.Model)
</div>
Controller:
[HttpPost]
public ActionResult AjaxTest(MyViewModel model)
{
model.A = "A"
return PartialView("_UpdatableContent", model);
}
Partial view _UpdatableContent:
#Html.HiddenFor(x => x.A)
#if (Model.A == "A")
{
//Draw
}
Try adding this.Model to your ActionLink following:
#Ajax.ActionLink("Click me", "AjaxTest", "Controller", this.Model, new AjaxOptions() { UpdateTargetId = "updatePanel" })
This method passes the model back into the request, which should allow the update to happen.
Probably my biggest gripe with ASP.NET MVC is the fact that the various "Helper" functions are overloaded to the nth-degree, and not always consistently in terms of the order the arguments appear...
Hope that helps :)
I had this very same problem. Setting HttpMethod = "Post" in the AjaxOptions fixed it for me, thanks Sergejs.
My final, working code is as follows
#{
AjaxOptions ajaxOptions = new AjaxOptions
{
HttpMethod = "Post",
LoadingElementId = "product-adding-" +#Model.Product.Id,
LoadingElementDuration = 100,
OnSuccess = "AddedToCart"
};
}
<div>
#Ajax.ActionLink("Add to cart",
"AddToCart",
"Cart",
new { id = Model.Product.Id, returnUrl = Request.Url.PathAndQuery },
ajaxOptions,
new { #class = "button" })
<img id="product-adding-#Model.Product.Id" src="~/Images/ajax_loader.gif" />
</div>

data-val attributes not generated in partialview created with Html.ActionLink in ASPNET MVC3

I've this structure
View
Html.RenderPartial (1)
Html.RenderPartial (2)
Then in each one of those Partial Views I have
#Ajax.ActionLink("Edit", "EditMethod", null, new AjaxOptions
{
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "divEditContent"
}, new { #class = "my-edit" })
And when clicked it renders another partial,replacing the div "divEditContent" with something like:
public PartialViewResult EditContactInformation()
{
return PartialView("_MyEdit", GetDetails());
}
_MyEdit partial has something like:
#using (Ajax.BeginForm("SaveContactInformation", "MyBsol", new AjaxOptions
{
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "divContactInformationContent"
}))
{
<script type="text/javascript">
$(function () {
$('form#ajaxForm').find('a.submit-link').click(function () {
$('form#ajaxForm').submit();
});
})
</script>
Save
#Ajax.ActionLink("Cancel", "CancelEdit", null, new AjaxOptions
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "divContent"
}, new { #class = "my-cancel" })
#Html.TextBoxFor(model => model.Title, new { #class = "txt-input", placeholder = "Eg. Mr, Mrs, Ms" })
#Html.ValidationMessageFor(model => model.Title)
}
The problem is that data-val atttributes are not rendered for the input, BUT if I put the last partial (_MyEdit) where the Ajax.ActionLink (1) it DOES render them.
Is this a bug? Any workaround?
Thanks in advance! Guillermo
UPDATE
I've found something really interesting, if I go (in Chrome or Firefox with Firebug) and click on View Source I don't see data-val attributes, but if I click on Inspect Element I see them..weird...
If you want the data validation tags to be there, you need to be in a FormContext. Hence, if you're dynamically generating parts of your form, you need to include the following line in your partial view:
#{ if(ViewContext.FormContext == null) {ViewContext.FormContext = new FormContext(); }
You then need to make sure you dynamically rebind your unobtrusive validation each time you add/remove items:
$("#form").removeData("validator");
$("#form").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse("#form");

Read htmlAttribute in controller

I have Ajax.ActionLink with htmlAttribute param
<%= Ajax.ActionLink("cool", "ViewCategory", new { id = elem.ID }, new AjaxOptions { UpdateTargetId = "score_" + elem.ID.ToString() }, new { myAttr = 123 } )%>
How can I read this attribute in controller method?
You can't.
All the htmlAttribute param does is instruct the generation of additional attributes to be added to the anchor html with it is sent to the client. These attributes are not included in the request when the anchor is clicked.
Place the attribute along side the id new {id = elem.ID, UpdateTargetID = ...} this should be included in the URL.

Html.BeginForm and adding properties

How would I go about adding enctype="multipart/form-data" to a form that is generated by using <% Html.BeginForm(); %>?
As part of htmlAttributes,e.g.
Html.BeginForm(
action, controller, FormMethod.Post, new { enctype="multipart/form-data"})
Or you can pass null for action and controller to get the same default target as for BeginForm() without any parameters:
Html.BeginForm(
null, null, FormMethod.Post, new { enctype="multipart/form-data"})
You can also use the following syntax for the strongly typed version:
<% using (Html.BeginForm<SomeController>(x=> x.SomeAction(),
FormMethod.Post,
new { enctype = "multipart/form-data" }))
{ %>
I know this is old but you could create a custom extension if you needed to create that form over and over:
public static MvcForm BeginMultipartForm(this HtmlHelper htmlHelper)
{
return htmlHelper.BeginForm(null, null, FormMethod.Post,
new Dictionary<string, object>() { { "enctype", "multipart/form-data" } });
}
Usage then just becomes
<% using(Html.BeginMultipartForm()) { %>

Resources