I want my Ajax.ActionLink to pass a viewModel property to action.
Here is my ViewModel
public class ViewModel
{
public string Searchtext { get; set; }
}
My .cshtml
#Ajax.ActionLink("Bottom3", "Bottom3",new { name = Model.Searchtext}, new AjaxOptions
{
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "pointsDiv"
})
using(Html.BeginForm("Bottom3", "Home", FormMethod.Get))
{
#Html.TextBoxFor(x => x.Searchtext)
<button type="submit">Search</button>
}
<div id="pointsDiv"></div>
}
My Controller action:
public PartialViewResult Bottom3(string name)
{
var model = db.XLBDataPoints.OrderBy(x => x.DataPointID).Take(3).ToList();
return PartialView("Partial1", model);
}
But the name parameter passed to the action is always null. How do I solve this?
In your code... you have 2 different ways of posting to the server: the link and the form button.
The problem is that the ActionLink has no way to get the value from the input in client side... just the original value.
If you press the Search button, you will see a value posted.
Now, you can use some jQuery to modify a standard ActionLink (not the Ajax.ActionLink):
https://stackoverflow.com/a/1148468/7720
Or... you can transform your Form in order to do a Ajax post instead of a normal one:
https://stackoverflow.com/a/9051612/7720
I did this for a model of mine like so. I ONLY supported the HttpPost method. So add the HttpMethod="POST" to your Ajax.ActionLink
[HttpPost]
public ActionResult Accounts(ParametricAccountsModel model)
{
if (model.Accounts == null)
{
GetAccountsForModel(model);
}
if (model.AccountIds == null)
{
model.AccountIds = new List<int>();
}
return View(model);
}
On the razor view
#Ajax.ActionLink(
"Add Account to Order", "Accounts", "Parametric", null,
new AjaxOptions() { InsertionMode = InsertionMode.Replace, UpdateTargetId = "...", HttpMethod = "POST" },
new { #id = "AddParametricAccountLink" })
The model has a list of selected account ids. So in javascript, I modified the href of the action link dynamically.
function UpdateParametricAccountAction() {
var originalLink = '/TradeNCashMgmt/Parametric/Accounts';
var append = '';
var numberOfRows = $('#ParametricAccounts').find('.parametric-account- row').size();
for (var i = 0; i < numberOfRows; i++) {
if (i != 0) {
append += '&';
}
else {
append = '?';
}
var idValue = $('#NotionalTransactionsAccountId_' + i).val();
append += 'AccountIds%5B' + i + '%5D=' + idValue;
}
$('#AddParametricAccountLink').attr('href', originalLink + append);
}
Since the model binder looks for parameter names in the query string and form submission, it will pick up values using the href. So I posted a model object using the querystring on my Ajax.ActionLink. Not the cleanest method, but it works.
Related
i work with Ajax.BeginForm
#model Shared.DataContracts.ConfigurationTransports
#using (Ajax.BeginForm("Save", "ConfigurationTransports",
new AjaxOptions
{
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace
}))
{
Html.RenderPartial("~/Views/ConfigurationTransports/ConfigurationPartialContent.cshtml", Model);
}
And my easy form
#model Shared.DataContracts.ConfigurationTransports
#Html.DevExpress().Label(s =>
{
s.Name = "Id";
s.ClientVisible = false;
}).Bind(Model.Id).GetHtml()
#Html.DevExpress().CheckBox(settings =>
{
settings.Name = "checkBoxUseStop";
settings.Properties.ValueUnchecked = 0;
settings.Properties.ValueChecked = 1;
settings.Text = Resources.UseStops;
}).Bind(Model.UseStop).GetHtml()
#Html.DevExpress().Button(settings =>
{
settings.Name = "btnSave";
settings.UseSubmitBehavior = true;
}).GetHtml()
When I click save a post to method Save and parameter ConfigurationTransports is empty without value, but if i load my form i have there values from my send object.
public ActionResult Save(ConfigurationTransports transport)
{
//Some logic method
return View("Index", preprava.GetData());
}
I read a lot of topic on devexpress forum, but i cant find solution.
Do you have any idea?
thx
decorate your Action with [HttpPost] Annotation
[HttpPost]
public ActionResult Save(ConfigurationTransports transport)
{
//Some logic method
return View("Index", preprava.GetData());
}
I have an Ajax form that updates the partial view it's in, but I need it to update a second partial view as well. I'd like to do this without merging them both into one view and updating that.
I think my best bet is to use a regular jQuery Ajax call on the form's onsuccess, but I don't know what parameters to use so I can just call a Controller Action that returns the partial to have it work.
My form is set up with
#using (Ajax.BeginForm("UpdateDateRange",
new { name = Model.Modules[i].Name },
new AjaxOptions { UpdateTargetId = Model.Modules[i].Name.Replace(" ", "_") + "_module" }
))
{ [Input fields] }
In your onSuccessmethod you can make another ajax call.
So for example in your OnSuccessMehtod call "MethodX"...which would do a ajax call and update a div on your page with returned result
var MethodX = function(id)
{
$.get("ActionName?id=" + id, function (result) {
$("#myAnotherdiv").html(result)
}, 'html');
}
In response to ajax call you can send two partial view that you want with this helper:
public static class MvcHelpers
{
public static string RenderPartialView(this Controller controller, string viewName, object model)
{
if (string.IsNullOrEmpty(viewName))
viewName = controller.ControllerContext.RouteData.GetRequiredString("action");
controller.ViewData.Model = model;
using (var sw = new StringWriter())
{
ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
viewResult.View.Render(viewContext, sw);
return sw.GetStringBuilder().ToString();
}
}
}
And in controller:
return Json(new { view1 = this.RenderPartialView(...), view2 = this.RenderPartialView(...) });
and in success you can get two partialView and replace them with old ones:
function success(data)
{
$("someSelectorToSelectPartial1").html(data.view1);
$("someSelectorToSelectPartial2").html(data.view2);
}
I am using #Ajax.Beginform in my View which is tightly bound to the ViewModel.
I've #Html.ListBoxFor inside my form. I add and delete items from the listbox using jQuery. Now what I am want to achieve is that onpress of the submit button, it should send full data present in the listbox regardless of which are selected. Currently it sends the list to controller if I select all the item in the listbox and press submit button. But I don't want to do that. Any idea as to how to achieve this?
Can it be sent as a form parameter.
#using (Ajax.BeginForm("SaveTextComponent", "LoanFilterEditor", new{ param1 = Model.listBoxItem}, new AjaxOptions { HttpMethod = "POST", OnSuccess = "SUCCESS" }))
I try to accept the parameter in the controller like this
public ActionResult SaveTextComponent(TextComponentViewModel model, List<SelectListItem> list)
{
}
But list is null.. Please help.
Maybe you can use this javascript to select all items at your listbox and then, send it to controller:
function listbox_selectall(listID, isSelect) {
var listbox = document.getElementById(listID);
for(var count=0; count < listbox.options.length; count++) {
listbox.options[count].selected = isSelect;
}
}
And after that, you can call the function on your form in this way:
<script>
function submit() {
listbox_selectall('righthand_side_listbox_id', true);
return true;
}
</script>
<form onsubmit="return submit()">
...
</form>
Credits to Viral Patel blog
You can follow my example:
Model:
pulic class TextComponentViewModel {
public int[] SelectedListItem { get; set; }
public List<Item> ListItem { get; set; }
}
public class Item {
public int Id { get; set; }
public String Name { get; set; }
}
View:
#model TextComponentViewModel
#using (Ajax.BeginForm("SaveTextComponent", "LoanFilterEditor", null, new AjaxOptions { HttpMethod = "POST", OnSuccess = "SUCCESS" }, new {name = "mainForm", id = "mainForm"}))
{
#Html.ListBoxFor(model => model.SelectedListItem , new MultiSelectList(Model.ListItem, "ID", "Name"))
for(var i = 0; i < Model.ListItem.Count();i++ )
{
#Html.HiddenFor(m => m.ListItem[i].Id)
#Html.HiddenFor(m => m.ListItem[i].Name)
}
<input type = "submit" id="submitButton" />
}
Controller:
public ActionResult SaveTextComponent(TextComponentViewModel model)
{
}
Script:
$("#submitButton").click(function(){
$("#mainForm").submit();
});
i have the following repository method to search for users containing a search parameter:-
public IEnumerable<User> searchusers2(string q)
{
return from u in entities1.Users
where (u.UserID.Contains(q) || string.IsNullOrEmpty(q))
select u;
}
which is called suing the following action method:-
public ActionResult QuickSearch(string term)
{
var users = r.searchusers2(term);
users.Select(a => new { value = a.UserID });
return Json(users, JsonRequestBehavior.AllowGet);
}
and on the view i have the following code:-
#using (Ajax.BeginForm("Search", "User", new AjaxOptions
{
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "searchResults",
LoadingElementId = "progress"
}))
{
<input type="text" name="q" data-autocomplete-source="#Url.Action("QuickSearch", "User")" />
<input type="hidden" name="classid" value="#ViewBag.classid"/>
<input type="submit" value="Search" />
}
the above code is not working but if i change my action method to be as follow (without using a repository to perform the search) then the auto complete will work fine,,, so what might be causing this problem:-
public ActionResult QuickSearch(string term)
{
var users = entities1.Users
.Where(e => e.UserID.Contains(term))
.Select(r => new {value = r.UserID });
return Json(users, JsonRequestBehavior.AllowGet);
}
In the repository-version you're returning the whole User object in Json, The Select in
public ActionResult QuickSearch(string term)
{
var users = r.searchusers2(term);
users.Select(a => new { value = a.UserID });
return Json(users, JsonRequestBehavior.AllowGet);
}
is doing nothing because you're not storing the returned values, you'll either need to chain the call together, e.g:
public ActionResult QuickSearch(string term)
{
var users = r.searchusers2(term).Select(a => new { value = a.UserID });
return Json(users, JsonRequestBehavior.AllowGet);
}
or use a separate variable:
public ActionResult QuickSearch(string term)
{
var users = r.searchusers2(term);
var values = users.Select(a => new { value = a.UserID });
return Json(values, JsonRequestBehavior.AllowGet);
}
In my Action for Editing an item in my model I have:
ViewBag.PossibleSource = context.Source.ToList();
In my View I have:
#Html.DropDownListFor(model => model.SourceID, ((IEnumerable<btn_intranet.Areas.DayBook.Models.DayBookSource>)ViewBag.PossibleSource).Select(option => new SelectListItem
{
Text = (option == null ? "None" : option.SourceName),
Value = option.SourceID.ToString(),
Selected = (Model != null) && (option.SourceID == Model.SourceID)
}))
In Chrome this works as expected. When I pass a model to my view, the current value that's set in my model is the selected value in the list. But in IE8 and 9 it's selected value is the ORIGINAL value my model was set as even though the update does work. So if I selected "hello" originally and then edited to "world". In chrome when i reload the page it will be set to "world" but in IE "hello" is selected in the dropdown even tho "world" is set in my database for my model. It is worth noting these are updated via AJAX
EDIT:
Ajax.Actionlink:
#Ajax.ActionLink(item.ItemNumber, "EditItem", new { id = item.QuoteLineID, enquiryId = item.EnquiryID }, new AjaxOptions()
{
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "EditItem"
})
This loads the form onto the view.
Ajax.BeginForm:
#using (Ajax.BeginForm("EditItem", new { controller = "QuoteLines" }, new AjaxOptions()
{
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "Summary"
}, new { #class = "manual-search cf" }))
{
...Other Model inputs
#Html.DropDownListFor(model => model.SourceID, ((IEnumerable<btn_intranet.Areas.DayBook.Models.DayBookSource>)ViewBag.PossibleSource).Select(option => new SelectListItem
{
Text = (option == null ? "None" : option.SourceName),
Value = option.SourceID.ToString(),
Selected = (Model != null) && (option.SourceID == Model.SourceID)
}))
<input type="submit" class="update-items" value="Update Line" />
}
EditItem Action GET request:
public virtual ActionResult EditItem(int id)
{
try
{
DayBookQuoteLines q = context.QuoteLines.Single(x => x.QuoteLineID == id);
ViewBag.PossibleSource = context.Source.ToList();
if (Request.IsAjaxRequest())
{
return PartialView("_EditItem", q);
}
else
{
return RedirectToAction("SalesDetails", new { controller = "Enquiries", id = q.EnquiryID });
}
}
catch (Exception ex)
{
return PartialView("_Error", ex.Message);
}
}
EditItem Action POST request:
[HttpPost]
public virtual ActionResult EditItem(DayBookQuoteLines q)
{
try
{
ViewBag.PossibleSource = context.Source.ToList();
if (ModelState.IsValid)
{
context.Entry(q).State = EntityState.Modified;
context.SaveChanges();
return PartialView("_GetSummary", context.Vehicles.Where(x => x.EnquiryID == q.EnquiryID).ToList());
}
return PartialView("_EditItem", q);
}
catch (Exception ex)
{
return PartialView("_Error", ex.Message);
}
}
I've fixed it, I renamed my GET request for EditItem to EditItemGet and then in my #Ajax.ActionLink I did:
#Ajax.ActionLink(item.ItemNumber, "EditItemGet", new { id = item.QuoteLineID, enquiryId = item.EnquiryID }, new AjaxOptions()
{
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "EditItem",
HttpMethod = "POST"
})
It was a Cache issue. Thats why it only failed in IE which likes Cache. I read before that making the request a POST request prevents Caching.