I'm trying to create an Item edit screen where the user can set a property of the Item, the ItemType. Ideally, when the user returns to the screen, the dropdown would display the ItemType already associated with the Item.
As it is, regardless of what the item.ItemType is, the dropdown will not reflect that in the dropdown. Is there a way around this?
For reference, my code at the moment is:
<div class="form-group">
#Html.LabelFor(model => model.ItemType, new { #class = "control-label col-xs-4" })
<div class="col-xs-8">
#Html.DropDownListFor(model => model.ItemType, (SelectList)ViewBag.ItemType, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.ItemType, String.Empty, new { #class = "text-danger" })
</div>
</div>
The ViewBag is set with the following:
var ItemType = Enum.GetValues(typeof(ItemType));
ViewBag.ItemType = new SelectList(ItemType);
If you're using ASP.NET MVC 5, try just using the EnumHelper.GetSelectList method. Then you don't need ViewBag.ItemType.
#Html.DropDownListFor(model => model.ItemType, EnumHelper.GetSelectList(typeof(ItemType)), new { #class = "form-control" })
If not, you might need to specify the data value and data text fields of the select list.
var itemTypes = (from ItemType i in Enum.GetValues(typeof(ItemType))
select new SelectListItem { Text = i.ToString(), Value = i.ToString() }).ToList();
ViewBag.ItemType = itemTypes;
Then since it's an IEnumerable<SelectListItem> you'll need to change your cast.
#Html.DropDownListFor(model => model.ItemType, (IEnumerable<SelectListItem>)ViewBag.ItemType, new { #class = "form-control" })
Eventually I found a fix - manual creation of the list.
<select class="form-control valid" data-val="true"
data-val-required="The Item Type field is required." id="ItemType" name="ItemType"
aria-required="true" aria-invalid="false" aria-describedby="ItemType-error">
#foreach(var item in (IEnumerable<SelectListItem>)ViewBag.ItemType)
{
<option value="#item.Value" #(item.Selected ? "selected" : "")>#item.Text</option>
}
</select>
Try to keep as much of the logic outside of the View and in the Controller.
I saw in your self answer that it looks like you have an enum selected from wihin your controller.
I have a DropDownList in one of my apps that contains a list of Enums. It also has a default value selected, but also has specific enums available to the user. The default selection can be set from within the controller.
This example is based on what my needs were, so you'll need to adapt to your case.
In the controller:
public ActionResult Index()
{
ViewBag.NominationStatuses = GetStatusSelectListForProcessView(status)
}
private SelectList GetStatusSelectListForProcessView(string status)
{
var statuses = new List<NominationStatus>(); //NominationStatus is Enum
statuses.Add(NominationStatus.NotQualified);
statuses.Add(NominationStatus.Sanitized);
statuses.Add(NominationStatus.Eligible);
statuses.Add(NominationStatus.Awarded);
var statusesSelectList = statuses
.Select(s => new SelectListItem
{
Value = s.ToString(),
Text = s.ToString()
});
return new SelectList(statusesSelectList, "Value", "Text", status);
}
In the view:
#Html.DropDownList("Status", (SelectList)ViewBag.NominationStatuses)
This approach will automatically set the default item to the enum that was selected in the controller.
Related
I am new to Razor, I pass dropdown list as a viewbag and another values, when drop down list show in web it has selected values but i haven't set the any selected value, I think I use same name in viewbag value and dropdownlist value,it can be happen?
This is the viewbag,here i set the values and drop downlist:
ViewBag.GlobalInstance = globalInstance;
ViewBag.LegislativeCode = legislativeCode.Trim();
ViewBag.Legislatives = new SelectList(legislativeEntities, "LegislativeCode", "LegislativeName");
This is frontend code:
#if (ViewBag.GlobalInstance == true)
{
<div class="col-xs-5 hcm-form_controller mandatory gap" >
<label for="LegislativeCode" class="w-100" mi-resourcekey="atr-LegislativeCode" >Legislative Entity</label>
#Html.DropDownListFor(m => m.LegislativeCode, ViewBag.Legislatives as SelectList, "--- Select ---", new { #class = "calc-w-100" })
</div>
}
It seems that the page model has a value for LegislativeCode,
m => m.LegislativeCode
so when there is a same LegislativeCode in the ViewBag.Legislatives, this option will be selected.
In the controller Index I have the following:
ViewBag.Assignees = (await GetAllUsers()).Select(a =>
new SelectListItem
{
Text = a.DisplayName,
Value = a.Username,
Selected = a.DisplayName == "John Smith"
}).OrderBy(x => x.Text).ToList();
In the View, I have the following:
#Html.DropDownListFor(model => model.Assignee,
ViewBag.Assignees as List<SelectListItem>,
"Select Assignee",
new { id = "ddlAssignee", #class = "form-control"})
The dropdownlist populates as expected, however, the default (selected = true) value, which does exist, does not get set. Can someone advise what is wrong in the above?
UPDATE:
By Changing the SelectListItem.Value to a.DisplayName (same as SelectedListItem.Text) I achieved it. Still not sure what prevents the dropdownlist from displaying the item with Selected = true
If the model.Assignee comes with value, and if it is an int it will be defaulted to 0, it will override the SelectListItem selected value.
I suggest to set up the model.Assignee.
Here two ways that i use.
WAY 1
#Html.DropDownListFor(model => model.Assignee,
ViewBag.Assignees as List<SelectListItem>,
"Value", // property to be set as Value of dropdown item
"Text", // property to be used as text of dropdown item
"1"), // value that should be set selected of dropdown
new { id = "ddlAssignee", #class = "form-control"})
WAY 2
<select name="SelectName" value="1" class="w-100">
#foreach (var item in ViewBag.Collection) {
<option value="#item.Id">#item.Name</option>
}
</select>
I hope it work for you
#Html.DropDownListFor how to set default value
In your view set:
#Html.DropDownListFor(model => model.Assignee,
ViewBag.Assignees as List<SelectListItem>,
"Select Assignee",
new { id = "ddlAssignee", #class = "form-control", #value = "Default value"})
When you have list already defined.
Use This
#Html.DropDownList("CoverageDropDown", new SelectList(Model.youList, "Code", "Description",item.seletecItem), "Select")
I'm displaying a dropdown list for countries, which is populated from a database call in the controller. On page load I would like the selected value to default to 'United States'. How do I do this?
Code from view:
<div class="form-group">
#Html.LabelFor(m => m.Country)
#Html.DropDownListFor(m => m.Country, new SelectList(Model.CountriesDDL, "CountryCode", "Country"), "--Select--", new { #class = "form-control" })
</div>
In your GET action, you can set the value of Country property to the CountryCode of United states (or whatever country you want to set as default) of your view model
public ActionResult Show()
{
var vm = new YourViewModel();
vm.CountriesDDL = GetCountriesFromSomeWhere();
vm.Country="United States";
return View(vm);
}
Assuming Country is of type string
I have the following properties
public SelectList ListActivities { get; set; } // Will load all hobbies i,e football, golf etc and will be displayed in a dropdown
public List<string> SelectedActivities { get; set; } // Trying to set with multiple selected values.
This is my view.
<div class="col-lg-11">
#Html.DropDownListFor(m => m.UserDetails.SelectedActivities, Model.UserDetails.ListActivities, "Please Select", new { #class = "form-control", multiple = "multiple", id = "listActivities" })
</div>
The issue I have is when I selected more then one option from the ActivitiesDropdown and press submit on my page and go back to the controller the SelectedActivities is null.
Can one shed some light on this please?
For multi-select you should use Html.ListBoxFor and not a Html.DropDownListFor because Html.DropDownListFor returns a single-selection select element.
So for this to work just change your view to:
<div class="col-lg-11">
#Html.ListBoxFor(m => m.UserDetails.SelectedActivities, Model.UserDetails.ListActivities, "Please Select", new { #class = "form-control", id = "listActivities" })
</div>
I'm having the same issue as this here I believe, but the workaround is not working for me.
My issue is that I have a child collection of models inside my main view's ViewModel. They contain data to be displayed in two fields, a dropdownlist and a password field. Each dropdownlist selection must be unique. Everything is saving and being sent to the view properly, however the dropdownlist are not binding to the selected values when the view is called but the password field is. They all default to the first selection, even though the property they are suppose to bind to is unique and only one can be the first value. Any help or insight is appreciated. Thanks.
Here is the part in my view where the issue is occurring. I have commented out my efforts and tried the above link's workaround to no avail:
#functions {
private IEnumerable<SelectListItem> Mark(IEnumerable<SelectListItem> items, object Id)
{
foreach (var item in items)
if (string.CompareOrdinal(item.Value, Convert.ToString(Id)) == 0)
item.Selected = true;
return items;
}
}
#for (int j = 0; j < Model.PasswordResetQuestionUserAnswers.Count(); j++)
{
#Html.Hidden("PasswordResetQuestionUserAnswers.Index", j)
#Html.HiddenFor(p => Model.PasswordResetQuestionUserAnswers[j].Id)
#Html.HiddenFor(p => Model.PasswordResetQuestionUserAnswers[j].UserId)
<div class="form-group">
<label class="col-md-2 control-label">Password Reset Question #(j+1)</label>
<div class="col-md-6">
#*#Html.DropDownList("PasswordResetQuestionUserAnswers[" + j + "].PasswordResetQuestionId", Model.PasswordResetQuestionList, new { #class = "form-control passwordQuestion" })*#
#*#Html.DropDownListFor(x => Model.PasswordResetQuestionUserAnswers[j].PasswordResetQuestionId, Model.PasswordResetQuestionList, new { #class = "form-control passwordQuestion" })*#
#Html.DropDownListFor(x => Model.PasswordResetQuestionUserAnswers[j].PasswordResetQuestionId, Mark(Model.PasswordResetQuestionList, Model.PasswordResetQuestionUserAnswers[j].PasswordResetQuestionId))
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">Password Reset Answer #(j+1)</label>
<div class="col-md-6">
#Html.Password("PasswordResetQuestionUserAnswers[" + j + "].Answer", Model.PasswordResetQuestionUserAnswers[j].Answer, new { #class = "form-control passwordQuestionUserAnswer" })
#*#Html.PasswordFor(x => Model.PasswordResetQuestionUserAnswers[j].Answer, new { #class = "form-control passwordQuestionUserAnswer" })*#
</div>
</div>
}
I just had this same problem. This syntax works for me:
#Html.DropDownListFor(x => x.ChildCollection[i].ChildID, new SelectList(ViewBag.ChildCollectionSelect as SelectList, "Value", "Text", Model.ChildCollection[i].ChildID))
Define the SelectList as new, then specifically set the selected value from the model.
This is an adaption to the example of above, for what worked for me in a similar scenario, where itm represents the child object in the collection. I'm not exactly sure what all is going on in that example -- too many "Questions", "Users", and "Answers", but say if you wanted a dropdown of users and it to be filled with the particular one that had been assigned to that child item:
foreach (var itm in Model.PasswordResetQuestionUserAnswers)
{
#Html.DropDownListFor(modelItem => itm.UserId,
new SelectList( (IEnumerable<SelectListItem>)ViewData["users"], "Value", "Text", itm.UserId),
htmlAttributes: new { #class = "form-control" }
)
}
Where you'd fill ViewData["users"] like this in the Controller method that renders the view:
var usersList = GetUsersList();
ViewData["users"] = usersList;
and have these supporting functions:
private static SelectListItem[] _UsersList;
/// <summary>
/// Returns a static category list that is cached
/// </summary>
/// <returns></returns>
public SelectListItem[] GetUsersList()
{
if (_UsersList == null)
{
var users = repository.GetAllUsers().Select(a => new SelectListItem()
{
Text = a.USER_NAME,
Value = a.USER_ID.ToString()
}).ToList();
users.Insert(0, new SelectListItem() { Value = "0", Text = "-- Please select your user --" });
_UsersList = users.ToArray();
}
// Have to create new instances via projection
// to avoid ModelBinding updates to affect this
// globally
return _UsersList
.Select(d => new SelectListItem()
{
Value = d.Value,
Text = d.Text
})
.ToArray();
}
Repository.cs
My Repository function GetAllUsers() for the function, above:
Model1 db = new Model1(); // Entity Framework context
// Users
public IList<USERS> GetAllUsers()
{
return db.USERS.OrderBy(e => e.USER_ID).ToList();
}
Users.cs
public partial class USERS
{
[Key]
public int USER_ID { get; set; }
[Required]
[StringLength(30)]
public string USER_NAME { get; set; }
}
Edit
After re-reading the question, it seems it was about posting password reset questions.
foreach (var itm in Model.PasswordResetQuestionUserAnswers)
{
#Html.DropDownListFor(modelItem => itm.PasswordResetQuestionId,
new SelectList( (IEnumerable<SelectListItem>)ViewData["pwordResetQuestions"], "Value", "Text", itm.PasswordResetQuestionId),
htmlAttributes: new { #class = "form-control" }
)
}
And you'd have to have a ViewData["pwordResetQuestions"] filled like this in the controller method that renders that view:
var questionsList = GetQuestionsList();
ViewData["questions"] = questionsList;
and these supporting functions/objects:
private SelectListItem[] _QuestionsList;
public SelectListItem[] GetQuestionsList()
{
if (_QuestionsList == null)
{
var questions = PasswordResetQuestionUserAnswers.Select(a => new SelectListItem()
{
Text = a.Answer, //? I didn't see a "PasswordResetQuestionText" call in your example, so...
Value = a.PasswordResetQuestionId.ToString()
}).ToList();
questions.Insert(1, new SelectListItem() { Value = "1", Text = "Mother's Maiden Name" });
questions.Insert(2, new SelectListItem() { Value = "2", Text = "Elementary school attended" });
_QuestionsList = questions.ToArray();
}
// Have to create new instances via projection
// to avoid ModelBinding updates to affect this
// globally
return _QuestionsList
.Select(d => new SelectListItem()
{
Value = d.Value,
Text = d.Text
})
.ToArray();
}
I hard-coded some questions in there - I kinda doubt you'd have a table for them, usually companies only have less than 10. But you could always do that database call like I did for the Users table if they were using a database table - which is why I left that example there.
I was having the same issue and fighting with it. The examples above got me over the hump, but I was able to simplify using the code the way you have it, with one modification:
Original Code
#Html.DropDownListFor(x => Model.PasswordResetQuestionUserAnswers[j].PasswordResetQuestionId, Model.PasswordResetQuestionList, new { #class = "form-control passwordQuestion" })
Update Code: (Wrap it with a new SelectList)
#Html.DropDownListFor(x => Model.PasswordResetQuestionUserAnswers[j].PasswordResetQuestionId, new SelectList(Model.PasswordResetQuestionList, "Value", "Text", Model.PasswordResetQuestionUserAnswers[j].PasswordResetQuestionId, new { #class = "form-control passwordQuestion" })
This eliminates the need for the ViewBag or ViewData.