DropDownListFor does not set selected value - asp.net-mvc

I have a view that is displaying a Drop down list using the HTML helper DropDownListFor
<%: Html.DropDownListFor(Function(model) model.Manufacturer, New SelectList(Model.ManufacturerList, Model.Manufacturer))%>
My controller is passing the View a ViewModel containing the Manufacturer and the ManufacturerList
Function Search(ByVal itemSrch As ItemSearchViewModel) As ActionResult
'some code mapping and model code'
Return View(itemSrch)
End Function
My ViewModel is nothing crazy just fills the ManufacturerList with a list of string values and then the Manufacturer property is just a string value containing the selected value from the drop down list.
Public Property Manufacturer As String
Public Property ManufacturerList() As List(Of String)
I'm having an issue with the view setting the selected value on the drop down list if we are reloading the Search View. I've checked the View Model (ItemSearchViewModel) when it comes into the Search function and the Manufacturer is populated with the proper selected value and successfully passes that value back to the Search View. At some point the data passed to the view doesn't seem to populate the selected value, was wondering if anyone had some ideas on why this is happening and what I can do to fix it.
Thanks

Didn't get much for answers on this so started digging into how I could fix this somewhat easily. Also in my research this seemed to be a common problem for many people with the DropDownListFor HTML Helper. I figured there had to be a way to get this working since I knew the selected value property from my ViewModel was actually getting passed to the View. So javascript and jQuery to the rescue, I ended up trying to set the selected value using the jQuery .ready function and was able to successfully get this to work. So here's my jQuery fix:
$(document).ready(function() {
$("#Manufacturer").val("<%: Model.Manufacturer %>");
});
For sake of making this easy to follow I used the full .ready syntax, or you can just use $(function () { 'code' });
If you want to solve this without using jQuery you can just use basic javascript syntax as well, it'll look something like this:
document.getElementByID("Manufacturer").Items.FindByValue("<%: Model.Manufacturer %>").Selected = true;
If you using the plain javascript call make sure to call this when the page is done loading data to the dropdownlist.
In either case all this code is doing is setting the selected value on the drop down list on the client side from the passed in Manufacturer value from the Model.
If you have any other ways to solve this problem please let me know, but this is working for me and hopefully it'll help someone else with their problem.
Thank,

I've done a similar quick-fix in JQuery today to fix this behaviour too :
$(document).ready(function() {
$(".wrapper<%: Model.Language %> option[value=<%: Model.Language %>]").attr("selected","true");
});
Though I could share it with others if needed.
I'd still like to see a real patch to this problem so many persons seems to have in a different way, maybe with an extension method of the already existing DropDownListFor Html.helper method.

Related

Pre-populate ListBox / MultiSelectList with selected items

Is there a way to pre-populate a MultiSelectList with selected items?
Example:
I have a single View that has the following ListBoxFor that will cause the page to update what it's displaying by allowing filtering of Model.Companies.
#Html.ListBoxFor(m => m.SelectedCompanies, new MultiSelectList(Model.Companies, "IdString", "CompanyName")
What I'd like to have happen is after the update, the MultiSelectList will have the items that were selected before the page updated and refreshed. Does that mean I need to return SelectedCompanies with what was selected, or is there another way?
I am using the javascript library Chosen for usability of the ListBox on the client side, but I don't think that this affects what I'm trying to do.
Sometimes, JS libaries can interfere with your desired results. I can't speak for Chosen JS library, but inspect the markup and see how it renders. As long as it still has the listbox on the client (it must have some input element defined somewhere; my guess it hides it and updates the values as they are selected), then yes it should integrate fine.
However, when the controller posts back, you have to repopulate the Model.SelectedCompanies property with whatever values came back from the POST operation to the controller. The property should still have the selected companies if you return a View from the POST operation. If you are using a RedirectToAction instead, you'd have to store the selections in TempData.

Why is CascadeFrom() not doing anything?

I'm really new to Kendo UI, and I'm having problems with CascadeFrom() not calling an action on my controller. Here's the bare bones of my problem:
// The parent dropdown
<select id="Testing">
<option value="0">Vehicle</option>
<option value="1">Driver</option>
<option value="2">Trailer</option>
</select>
// The dynamic dropdown
#(Html.Kendo().DropDownListFor(m => m.VDTId)
.DataValueField("Id")
.DataTextField("Item")
.DataSource(ds =>
{
ds.Read(c => c.Action("GetVDT", "CompanyVDTUnavailability")
.Data("getVDTSelection"))
.ServerFiltering(true);
})
.CascadeFrom("Testing"))
// Function to allow Kendo to pass a value to
// the type parameter of my GetVDT action.
function getVDTSelection() {
return {
type: parseInt($("#Testing").val())
};
}
The action is being called when the page first loads, and returns the correct data. The problem is, if I then make a selection from the Testing dropdown, the action is never invoked on the controller (I've verified this using a breakpoint on the action), meaning the dynamic dropdown never gets updated.
Looking through the official example, and other questions around SO, I can't see what I'm doing wrong. Could someone point me in the right direction, please?
Edit: I've tried Petur's solution below by changing the parent dropdown to the following:
#(Html.Kendo().DropDownListFor(m => m.Type)
.Name("Testing")
.DataValueField("Id")
.DataTextField("Text")
.BindTo(Model.UnavailabilityTypes))
This binds the parent dropdown correctly, but no longer invokes the controller action for the cascading dropdown even when the page first loads. Any suggestions?
Controller action signature as requested:
public JsonResult GetVDT(CompanyUnavailabilityType type)
Where CompanyUnavailabilityType is an enum.
Kendo DropDownList can cascade only from another Kendo DropDownList/ComboBox. Turn the first widget into kendo DropDownList and it should start working properly.
I think the problem is that getVDTSelection() is returning an int or string value not an Enum value. Change your method sig to an int if not, try a string and the method described in my comment
public JsonResult GetVDT(int type)
{
//AllowGet might be needed as well
return Json(jsonObjx,JsonRequestBehavior.AllowGet);
}
Edit:
You can also try to Manually force the ddl to cascade. Ditch CascadeFrom and do it manually.
function OnChangeOfParentDDL(e){
var parentValue = $("#ParentDDL").val();
$("#ChildDDL").val("").data("kendoDropDownList").text("");//clear it out
var child = $("#ChildDDL").data("kendoDropDownList");
child.dataSource.read({ type : parentValue });
}
Both Petur and C Sharper were on the right track with the problem.
I did need to build the dropdown using Html.Kendo.DropDownList() (I've just verified this after getting the solution to work.)
The method signature on the controller was a problem, but only because I'd had old testing methods left on there, leading to an ambiguous call.
The major difficulty for me was that nothing was being reported in the debugger, so diagnosing the problem was a pain. In the end, I used the Network tab of the Firefox web developer tools to ensure the Ajax request was indeed being sent, and it was. Inspecting that request showed it was leading to an ambiguous call on the controller.
Also, to clear up comments from C Sharper's answer:
The parseInt() call is not required.
The call will correctly map to an enum on the server-side, meaning the method signature I posted in my question is correct.

Infragistics grid's GET returning empty response

I'm trying to use Infragistics' grid to display a list of items from my Database. I'm using code-first method with Entity Framework in an MVC application with Razor engine. Every thing is working fine in the view except the Infragistics grid.
Here is my home view:
#using Infragistics.Web.Mvc
#model IEnumerable<BusinessModel.Models.TestPlan>
#{
ViewBag.Title = "Home";
}
#( Html.Infragistics().Grid<BusinessModel.Models.TestPlan>(Model)
.AutoGenerateColumns(true)
.DataSourceUrl(Url.Action("igListTestPlan"))
.DataBind()
.Render())
Here is my controller:
[GridDataSourceAction]
public ActionResult igListTestPlan()
{
return View(service.getListTestPlan());
}
Using firebug I can clearly see that the request is sent with a status code "200 OK", but the response tab is empty. It also causes an error in the console (in infragistics.js):
Uncaught TypeError: Cannot read property 'length' of undefined
I guess it's because of the empty response.
What I tried:
Debugging my controller showed me that return View(service.getListTestPlan()); doesn't return an empty list: I have 3 valid items in.
I also tried Html.Infragistics().Grid<BusinessModel.Models.TestPlan>(Model__.ToList()) but nothing changed. Also Html.Infragistics().Grid(Model) tells me I've got invalid parameters
Thanks in advance.
I think I have a pretty good idea why you are getting this, happened to me as well.
The MVC wrappers provide defaults for the way the grid model handles data on the server (serializing the data source to an object with 'Records' of your data and supportive 'Metadata'). However, if you do that yourself since you don't define a key of your own you are stuck with a default key 'Records' that is used to filter the response and since it's not there..well you get 'undefined' data fed to the grid :)
So solutions:
1) Wrap your response and define matching key using the "ResponseDataKey" property of the grid. I am suggesting this because as far as I recall it's a good practice to wrap responses in a single object - think there were some security implications.
2) If you don't feel like doing this and just want to get it working now then set the "ResponseDataKey" to empty string ("" will do) so your response will be properly filtered(or rather not).
On the second part of binding the grid directly to model data in the view - you are correctly getting the error as far as I see. The DataSource property explicitly states the source must implement IQueryable instead of IEnumerable. Slap a .AsQueryable() in there and that should work fine as well.
Let me know if this helps :)

asp.net mvc: What is the correct way to return html from controller to refresh select list?

I am new to ASP.NET MVC, particularly ajax operations. I have a form with a jquery dialog for adding items to a drop-down list. This posts to the controller action.
If nothing (ie void method) is returned from the Controller Action the page returns having updated the database, but obviously there no chnage to the form. What would be the best practice in updating the drop down list with the added id/value and selecting the item.
I think my options are:
1) Construct and return the html manually that makes up the new <select> tag
[this would be easy enough and work, but seems like I am missing something]
2) Use some kind of "helper" to construct the new html
[This seems to make sense]
3) Only return the id/value and add this to the list and select the item
[This seems like an overkill considering the item needs to be placed in the correct order etc]
4) Use some kind of Partial View
[Does this mean creating additional forms within ascx controls? not sure how this would effect submitting the main form its on? Also unless this is reusable by passing in parameters(not sure how thats done) maybe 2 is the option?]
UPDATE:
Having looked around a bit, it seems that generating html withing the controller is not a good idea. I have seen other posts that render partialviews to strings which I guess is what I need and separates concerns (since the html bits are in the ascx). Any comments on whether that is good practice.
look at the ContentResult you can specify the mime type of what you return (text/html)
You could alternatively make a control that take a IEnumerable of whatever you put in the selectlist, and build it using the view engine. That way you keep the formatting of the html (in this case a list of options) into a view, and not in your code.
<%# Control Language="C#"Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Article>>"%>
<%foreach (var article in Model){%>
<option><%:article.Title %></option>
<%} %>
I think I would go for that second one
From what I understood, the jQuery dialog contains a form that, when submitted, will post to an action which updates the database with some information. You want to get the newly added database information and update the same form that was used to trigger the database update.
If that is the case, then I think the best clean and logical option is to return JSON serialization of the items to be put in the drop down right after you update the database. Then, using jQuery, you would clear the drop down and append option tags into it.
You can also write a new, seperate action that returns the JSON serialization of the database objects you need. You would have jQuery call another post to this action as a callback to your first ajax post (the one used to update the database).
Here is a quick snippet
public ActionResult UpdateDatabase(string something)
{
/// update the database
IEnumerable<Items> items = getItemsFromDatabase(); // or w/e
var vals = items.Select(x=> new { value = x.ID, text = x.Name }); // something similar
return Json(vals);
}
Personally, I would write a separate function that returns JSON. This ensure separation of concerns, and gives me a function I can use in many different places.
Returning a JsonResult with all the items is the most versatile and least-bandwidth intensive solution as long as you are happy to iterate through the list in jQuery and update your drop-down list.
Using a partial view is nice for HTML that you can .load(...) directly into your select, but less versatile.
I would go with the JsonResult.
In your Controller:
public JsonResult UpdateItem(string sItem)
{
// 1. Insert new item into database if not exist...
// {update code here}
// 2. retrieve items from database:
IEnumerable<Item> Items = GetItems();
// 3. return enumerable list in JSON format:
return new JsonResult{ Data = new {Items = Items, Result = "OK" }};
}
On client-side:
Iterate through Items array and add the items to your list.

How to get the selected value of a dropdown in the MVC View itself

I have a drop down in a MVC View, which is some thing like this:
Html.DropDownList(id, Range(0,10)
.Select(x => new SelectListItem {Text = x, Value = x}))
In the view itself, I need the selected value of this drop down. I know that I can access that in a JavaScript, but I am looking for a way to get it in the view itself from the drop down properties or something like that.
How can I access it? I tried to figure out some thing from intellisense but nothing relavant showed up, help is much appreciated.
Edit: I want the value after a few lines after the declaration of the drop down, I know that I can access it from JavaScript and by posting the form, Is there noway to access it on the view itself ?
Edit2: If its not possible to access it in view, please explain the reason, I am more interested in knowing it.
Thanks.
After reading at your question, it sounds like you want to have the drop down list supply a value for a lower section of the same page.
First and foremost, you will need to place the DropDownList within a form construct, as in:
<% using (Html.BeginForm("ProcessValue", "ThisPage")) { %>
<%= Html.DropDownList("DropID", Range(0, 10).Select(a=>new SelectListItem { Text = x, Value = x }) %>
<input type=submit value="Submit" />
<% } %>
You need to set up a few things ahead of time:
You have to have a submit button, or a similar construct, in order to retrieve the value of the DropID variable.
You need to set up an controller method that will handle the processing of the value, then redirect back to the original page with the selected value in the page's ViewData.
Finally, you need to set up the view so that the post-processing section will only display if you have a valid value in the DropID variable.
It's not as simple as just placing a DropDownList in a view and then using that value later on in the page. You have to get the controller involved to manage the data transport and you have to set up the single view to handle multiple states (ie. before the value is selected and after the selection takes place).
To get the selected value you could use either javascript or a controller action to which the form containing the select box is submitted.
The selected value will be in the FormCollection or QueryString collection with the name of the DropDown's ID in the controller action that receives the form submission from this view. You can either submit the values with a classic POST or GET or via AJAX, but you have to wire up a server-side action that processes that input.
There is a SelectList class as well wich allows you to define wich item will be selected.. and knowing that - you will know selected value..
Also.. if no value is selected explicitly, dropdowns tend to select the first item in the list.

Resources