DropDownListFor not selecting default - asp.net-mvc

I'm having problems trying to get a preselected value to work.
I've tried to include Selected in the SelectListItem but it doesn't pre-select.
Any clues as to why it's not matching up? Thanks for any help.
RetailerId is int. (it's not defined as enumerable)
Retailer is an enum, for example:
public enum Retailer
{
Sears = 10,
Macys = 20
}
Here is the View code :
#Html.DropDownListFor(x => x.RetailerId,
Enum.GetValues(typeof(Retailer)).Cast<Retailer>()
.OrderBy(o => o.GetDescription())
.Select(o => new SelectListItem() { Text = o.GetDescription(), Value = o.ToString(), Selected = (o.ToInt() == Model.RetailerId) }),
new { #data_placeholder = "Select Retailer", #class = "form-control" })

Your generating a collection of SelectListItem where the Value is either "Sears" or "Macys" which cannot be bound to property RetailerId which is an int.
Note that the Selected property of SelectListItem is ignored when binding to a model property. Internally the method sets the Selected property based on the value of the property your binding to, and since its an int, it does not match any of your options values and the first option is selected because something has to be.
You can make this work by modifying the .Select clause to
.Select(o => new SelectListItem() { Text = o.GetDescription(), Value = ((int)o).ToString() }),
Alternatively, change the model property to
public Retailer RetailerId { get; set; }
an the .Select clause to
.Select(o => new SelectListItem() { Text = o.GetDescription(), Value = o.ToString() }),

Related

Validate static dropdown in MVC5

I have on drop down.
Model
[Required(ErrorMessage = "Please selectvehicle")]
public string VehicleRequested { get; set; }
index.cshtml
#Html.DropDownList("VehicleRequested", new List<SelectListItem>
{
new SelectListItem{ Text="Active", Value = "1" },
new SelectListItem{ Text="Not-Active", Value = "0" }
})
#Html.ValidationMessageFor(model => model.VehicleRequested)
I cannot see the required feild validation append, M i wrong any where , please suggst
Your dropdownlist only has 2 items, one with value="0", the other with value="1" Both "0" and "1" are valid strings (neither are null) so validation always passes. Your property can never be invalid so you never get a validation error.
Its not really clear why your binding a int value to string property, and the fact you display only 2 values ("Active" and "Not-Active") suggests you property really should be a bool.
If you want to add an option such as "-please select-" that results in a validation error if one of the other 2 options is not selected, then use the overload that accepts optionLabel
#Html.DropDownList("VehicleRequested", new List<SelectListItem>
{
new SelectListItem{ Text="Active", Value = "1" },
new SelectListItem{ Text="Not-Active", Value = "0" }
}, "-Please select-")
#Html.ValidationMessageFor(model => model.VehicleRequested)
This will add the first option as <option value>-Please select-</option>. Note that the value attribute does not have a value, so if its selected when you submit, VehicleRequested will be null and you will see the error message.
Side note: Suggest you use the strongly typed helper - #Html.DropDownListFor(m => m.VehicleRequested, ...) and that you build the your Selectist in the controller and pass it to the view as a ViewBag or (better) a view model property.
Use #Html.DropDownListFor()
#Html.DropDownListFor((model => model.VehicleRequested, new List<SelectListItem>
{
new SelectListItem{ Text="Active", Value = "1" },
new SelectListItem{ Text="Not-Active", Value = "0" }
})

Dropdownlistfor selected item not selecting using viewbag

I have dropdownlistfor which is getting populated from viewbag string array
<td>#Html.DropDownListFor(m => Model[i].start_operation, new SelectList(ViewBag.ValidOpers))</td>
<td>#Html.DropDownListFor(m => Model[i].end_operation, new SelectList(ViewBag.ValidOpers))</td>
It is not selecting the selected item based on Model[i].start_operation and end_operation
ViewBag.ValidOpers = new[] { "One", "Two", "Three", "Four"};
Unable to figure out why it is not selecting. I check giving just a Html.DisplayFor(m=>Model[i].start_operation to check if it is getting the values and yes it is getting the value and displaying correctly in the label, but the same value is not getting selected in the dropdownlistfor.
To over-answer your question:
Try first adding a not-mapped member to your model class:
e.g.
[NotMapped]
static public List<SelectListItem> myListOptions { get; set; }
then in the controller you can have
MyNameSpace.Models.MyModel.myListOptions = db.myTable.Select(uA=> new SelectListItem{ Value = uA.myColumn, Text = uA.myColumn}).Distinct().OrderBy(uA=>uA.Text).ToList();
// if you want string constants use:
MyNameSpace.Models.MyModel.myListOptions = new List<SelectListItem>();
MyNameSpace.Models.MyModel.myListOptions.Add(new SelectListItem() {Text = "a", Value = "a"});
MyNameSpace.Models.MyModel.myListOptions.Add(new SelectListItem() {Text = "b", Value = "b" });
then in the view, you use:
<div class="editor-field">
#Html.DropDownListFor(model => model.myField, MyNameSpace.Models.MyModel.myListOptions )
#Html.ValidationMessageFor(model => model.myField)
</div>

Display ViewModel value with #Html.DropDownListFor

Let's say my database has a reference table that maps the values Zebra, Goat, and Dog onto the keys 0, 1, and 2, and a DropDownList where a user can select one of these values.
#Html.DropDownListFor(
m => m.Animal,
new SelectList(
new List<Object>{
new {value = 0, text = "Zebra"},
new {value = 1, text = "Goat"},
new {value = 2, text = "Dog"}
},
"value",
"text"
),
new { #class = "form-control" }
)
After the user's selection is saved to the database, I'm trying to figure out a way to display the value for m => m.Animal. It's saved as a 2, but I want the displayed text to read Dog. How do I set the default selected value on the #Html.DropFownListFor equal to the user's selection (e.g. 2), so the selected item displays the text Dog?
I'm seeing two possible meanings to your question, so I guess I'll just cover them both.
If you're talking about making the drop down show the proper selected value, Razor should take care of this for you. However, the fact that you're defining the actual SelectList object, without specifying the selectedValue param, may be getting in the way. Technically DropDownListFor only needs IEnumerable<SelectListItem>, not an actual SelectList, and it's usually better to pass it the former as it's both easier and less prone to error:
#Html.DropDownListFor(
m => m.Animal,
new List<SelectListItem> {
new SelectListItem { Value = "0", Text = "Zebra" },
new SelectListItem { Value = "1", Text = "Goat" },
new SelectListItem { Value = "2", Text = "Dog" }
},
new { #class = "form-control" }
)
If, however, you're talking about how to translate the value 2 into Dog at some later point in your code, then you should actually employ something like an enum. For example:
public enum Animals
{
Zebra = 0,
Goat = 1,
Dog = 2
}
Then, change your Animal property to be of this type:
public Animals Animal { get; set; }
Finally, and since you're running MVC5, you can just use:
#Html.EnumDropDownListFor(m => m.Animal, new { #class = "form-control" })
You don't even need to pass a list of options because the helper will just get them from the enum the Animal property is typed to.
Then, when you want to display the selected animal type, you just use:
#Html.DisplayFor(m => m.Animal)
And Dog or whatever it's set to will be output automatically.

Assign a value to select list (in a table) from a DB

I'm having trouble assigning the selected value to a select list (that is in a table) from a DB.
The value is defaulting to the first option even when a value is passed to it and it definitely passing from my controller to the view.
I have also tried a different select list that passes the value correctly on my form, and that select list also doesn't work. So I'm pretty sure it has something to do with the table
Here is a screenshot of the value passing.
Select List
public IEnumerable<SelectListItem> ListViewStatusOptions
{
get
{
return new[]
{
new SelectListItem { Value = "Scheduled", Text = "Scheduled" },
new SelectListItem { Value = "OFR-Out for Revision", Text = "OFR-Out for Revision" },
new SelectListItem { Value = "Tool Work Required", Text = "Tool Work Required" },
new SelectListItem { Value = "Delayed", Text = "Delayed" },
new SelectListItem { Value = "In Press", Text = "In Press" },
};
}
}
Select List in Table
#foreach (var item in Model) {
<td>
#Html.DropDownListFor(modelItem => item.ListViewStatus, item.ListViewStatusOptions, "Select", new { #id = #Html.ValueFor(modelItem => item.Id )})
</td>
}
You need to use a SelectList object new an array of SelectListItems.
Add this property to your method
public IEnumerable<SelectListItem> StatusOptions
{
get { return new SelectList(ListViewStatusOptions, "Value", "Name"); }
}
"Value" is the name of the property that contains the id of each item. You can have a list of any type of object not just SelectListItems. This is why is may seem unnecessary to pass "Value", Similarly, "Name" is the property that contains what to show the user.
Then change your razor code to
#foreach (var item in Model) {
<td>
#Html.DropDownListFor(modelItem => item.ListViewStatus, item.StatusOptions, "Select", new { #id = #Html.ValueFor(modelItem => item.Id )})
</td>
}
the proper binding for a list of values will be:
for (int i = 0; i < Model.Count; i++)
{
#Html.DropDownListFor(modelItem => modelItem[i].ListViewStatus, new SelectList(Model[i].ListViewStatusOptions, "Value", "Text", Model[i].ListViewStatus))
}
you have to use for loop instead of for-each because mvc will not generate proper input names if foreach is used and the posted data will be not resolved by action methods
My updated Razor Code.
As #ScottMacMaster explains,
You need to use a SelectList object new an array of SelectListItems.
"Value" is the name of the property that contains the id of each item.
You can have a list of any type of object not just SelectListItems.
This is why is may seem unnecessary to pass "Value", Similarly, "Name"
is the property that contains what to show the user.
I was receiving an error for Name so i changed it to Text
I then assign item.ListViewStatus as the object selected value
#Html.DropDownListFor(modelItem => item.ListViewStatus,
new SelectList(item.ListViewStatusOptions, "Value", "Text",item.ListViewStatus), "Select",
new { #id = #Html.ValueFor(modelItem => item.Id )})

Html.DropDownListFor does not select value

I have an action that retrieves data and sends it to a view. In a view I have two dropdown menus.
First drop down shows salutation (such as "Mr.", "Ms.", etc.) and does not select value I sent for some reason. The other dropdown shows language list and correctly selects value I sent to the view. The relevant code in view is shown below.
#Html.DropDownListFor(model => model.Salutation, ViewBag.salutation as IEnumerable<SelectListItem>)
#Html.DropDownListFor(model => model.Language, ViewBag.languages as IEnumerable<SelectListItem>)
In the controller I have the following code to get the dropdown data.
ViewBag.salutation = new List<SelectListItem>() {
new SelectListItem() { Text = "", Value = "" },
new SelectListItem() { Text = "Mr.", Value = "Mr." },
new SelectListItem() { Text = "Ms.", Value = "Ms." },
new SelectListItem() { Text = "Mrs.", Value = "Mrs." }
};
and
var languages = (from l in db.Languages.ToList()
select new SelectListItem()
{
Text = l.Language,
Value = l.LanguageId.ToString()
}).ToList();
languages.Insert(0, new SelectListItem() { Text = "", Value = "" });
ViewBag.languages = languages;
The only difference I could think of is that the languages dropdown has an integer as value, whereas salutation dropdown has text as value. Is this why the salutation dropdown doesn't work? I know I could go through each salutation List<SelectListItem> item and set Selected property based on the value I retrieved from database. But I was hoping there would be a cleaner way to do this.
Any ideas?
Thanks
UPDATE
I decided to do what I did for another project.
IList<SelectListItem> _salutation = new List<SelectListItem>()
{
new SelectListItem() { Value = "", Text = "" },
new SelectListItem() { Value = "Mr.", Text = "Mr." },
new SelectListItem() { Value = "Ms.", Text = "Ms." },
new SelectListItem() { Value = "Mrs.", Text = "Mrs." }
};
// I could put the following in the declaration above, but for testing purposes it's in foreach loop.
foreach (var item in _salutation)
{
// compare to what's retrieved from database
item.Selected = item.Value == _viewData.Salutation;
}
ViewBag.salutation = _salutation;
After foreach loop I output .Value, .Selected property of each item in _salutation and I get all the correct values with one item being selected. Inside the view I did the following.
#foreach (var item in ViewBag.salutation as IEnumerable<SelectListItem>)
{
<b>#item.Value : #item.Text : #item.Selected</b><br />
}
All the correct Text/Values come up but none are Selected! This happens if I output the values after I execute #Html.DropDownListFor(). If I output the ViewBag.salutation before the html helper the correct value is selected.
SOLUTION
I found the following article useful: DropDownListFor with ASP.NET MVC.
Instead of using ViewBag I added the following to the ViewModel. (Showing the part for salutations drop down.)
public class TheViewModel
{
private IList<string> _salutations = new List<string>() { "", "Mr.", "Ms.", "Mrs." };
public IEnumerable<SelectListItem> SalutationItems
{
get
{
var salutations = _salutations.Select(s => new SelectListItem { Value = s, Text= s });
return salutations;
}
}
// The rest of the ViewModel
}
And in the View I have the following.
#Html.DropDownListFor(model => model.Salutation, Model.SalutationItems)
Instead of just supplying the list to the DropDownListFor helper you could provide it a SelectList. The SelectList constructor takes the list and allows you to explicitly set the selected value as well as an overload that lets you specify the Text and Value fields.
#Html.DropDownListFor(model => model.Salutation,
new SelectList(ViewBag.salutation as IEnumerable<SelectListItem>,
"Value", "Text", Model.Salutation))
Try this,
#Html.DropDownListFor(m =>m.DDCountryModel,IEnumerable<SelectListItem>)ViewBag.salutation)
#Html.DropDownListFor(model => model.Language, IEnumerable<SelectListItem>)ViewBag.languages)
Your Model should be like this,
public class Model
{
public IEnumerable<SelectListItem> DDCountryModel{ get; set; }
public IEnumerable<SelectListItem> Language{ get; set; }
}

Resources