How do I set the selected value on a drop down list? Here is what I have so far:
#model Web.Models.PostGraduateModels.PlannedSpecialty
#Html.DropDownList("PlannedSpecialtyID")
//controller
[HttpGet]
public PartialViewResult PlannedSpecialty()
{
// Get Planned Specialty ID
var pgtservice = new PgtService();
PostGraduateModels.PlannedSpecialty plannedSpecialty = pgtservice.GetPlannedSpecialtyId();
// Get Data for Planned Specialty DropDown List from SpecialtyLookup
var pgtServ = new PgtService();
var items = pgtServ.GetPlannedSpecialtyDropDownItems();
ViewBag.PlannedSpecialtyId = items;
return PartialView(plannedSpecialty);
}
// service
public IEnumerable<SelectListItem> GetPlannedSpecialtyDropDownItems ()
{
using (var db = Step3Provider.CreateInstance())
{
var specialtyList = db.GetPlannedSpecialtyDdlItems();
return specialtyList;
}
}
// data access
public IEnumerable<SelectListItem> GetPlannedSpecialtyDdlItems()
{
IEnumerable<Specialty> specialties = this._context.Specialties().GetAll();
var selList = new List<SelectListItem>();
foreach (var item in specialties)
{
var tempps = new SelectListItem()
{
Text = item.Description,
Value = item.Id.ToString()
};
selList.Add(tempps);
}
return selList;
}
I would recommend you to avoid using ViewBag/ViewData/ Weekly typed code. Use strongly typed code and it makes it more readable. Do not use the Magic strings/ Magic variables. I would add a collection property to your ViewModel to hold the SelectList items and another property to hold the selected item value.
public class PlannedSpecialty
{
public IEnumerable<SelectListItem> SpecialtyItems { set;get;}
public int SelectedSpeciality { set;get;}
//Other Properties
}
and in your Get action, If you want to set some Item as selected,
public PartialViewResult PlannedSpecialty()
{
var pgtServ = new PgtService();
var vm=new PlannedSpecialty();
vm.SpecialtyItems = pgtServ.GetPlannedSpecialtyDropDownItems();
//just hard coding for demo. you may get the value from some source.
vm.SelectedSpeciality=25;// here you are setting the selected value.
return View(vm);
}
Now in the View, use the Html.DropDownListFor helper method
#Html.DropDownListFor(x=>x.SelectedSpeciality,Model.SpecialtyItems,"select one ")
Use the selected property of the SelectListItem class:
selList.Selected = true;
Related
I have a razor view in ASP.NET MVC looping over an array of objects from my model and generating corresponding html controls.
My html elements are properly bound, except my drop down lists who can't seem to select the value provided to them by the model.
My view: (in the hereby case, I'm simply displaying a list of countries)
#for (var i = 0; i < Model.answers.Count(); i++)
{
<div class="form-group">
...
#switch (Model.answers[i].Statement.QuestionType)
{
...
case ExternalEnums.QuestionTypeEnum.country:
#Html.DropDownListFor(Model => Model.answers[i].Value,
new SelectList(Model.Pays, "Value", "Text"))
break;
}
...
</div>
}
My view controller, generating the country list items and retrieving the existing model entries:
public class HomeIndexViewModel
{
private QuestionsModelContainer dbContext;
private AdmcommonEntities admCommonContext;
...
public List<Answer> answers { get; private set; }
private IEnumerable<SelectListItem> _countries;
public IEnumerable<SelectListItem> Pays
{
get
{
if (_countries == null)
SetCountries();
return _countries;
}
}
public HomeIndexViewModel()
{
Init(-1, null);
}
public HomeIndexViewModel(int page, string _pageWideError = null)
{
Init(page, _pageWideError);
}
private void Init(int page, string _pageWideError = null)
{
dbContext = new QuestionsModelContainer();
PageNum = page;
pageWideError = _pageWideError;
answers = GetAnswers();
...
}
private void SetCountries()
{
using (admCommonContext = new AdmcommonEntities())
{
var localEntities = admCommonContext.Pays.ToList();
var localList = new List<SelectListItem>();
localList.Add(new SelectListItem());
foreach (var item in localEntities)
{
var newItemList = new SelectListItem();
newItemList.Text = item.Libelle;
newItemList.Value = item.Libelle;
localList.Add(newItemList);
}
_countries = localList;
}
}
public List<Statement> GetStatements()
{
var statements = dbContext.StatementSet.Where(w => w.Page == PageNum).OrderBy(w => w.Order).ToList();
return statements;
}
public List<Answer> GetAnswers()
{
var statements = GetStatements();
var ExistingAnswers = new List<Answer>();
if (AdminPermissionManager.IsUserAuthenticated()) //Loading existing entries.
ExistingAnswers = Answer.GetExistingAnswers(statements, dbContext);
var answers = new List<Answer>();
foreach (var item in statements)
{
var answer = ExistingAnswers.Where(w => w.StatementId == item.Id).FirstOrDefault();
if (answer == null)
{
answer = new Answer();
answer.StatementId = item.Id;
answer.Statement = item;
}
answers.Add(answer);
}
return answers;
}
}
My model class, simply containing the value I'm trying to display:
[MetadataType(typeof(AnswerMetaData))]
public partial class Answer
{
...
public static List<Answer> GetExistingAnswers(List<int> statementIds, QuestionsModelContainer dbContext)
{
List<Answer> ExistingAnswers;
var usercode = AdminPermissionManager.GetUserCode();
ExistingAnswers = dbContext.AnswerSet.Where(w => statementIds.Contains(w.StatementId) && w.ChildCode == usercode).ToList();
return ExistingAnswers;
}
public static List<Answer> GetExistingAnswers(List<Statement> statements, QuestionsModelContainer dbContext)
{
var statementIds = statements.Select(w => w.Id).ToList();
return GetExistingAnswers(statementIds, dbContext);
}
}
public class AnswerMetaData
{
[InternalValidation]
public string Value { get; set; }
private class InternalValidationAttribute : ValidationAttribute
{
...
}
}
I'm sure there's something very obvious that I'm missing, but can't figure out what exactly :/...
You're nearly there actually, this part in the View:
#Html.DropDownListFor(
Model => Model.answers[i].Value,
new SelectList(Model.Pays, "Value", "Text")
)
You create a new selectlist - each time, but you already have a IEnumerable<SelectListItem> created, so you don't have to recreate that list. The only thing you might be missing (most likely) is the "Selected" item option.
If you already have a value selected (and it isn't the first one) it will not be selected dropdown option - also because you pass the value of the selected option as the "ID" of the field (not the actual value) - DropDownListFor is kinda weird in that regard.
So you want to change your #Html.DropDownListFor to something like this:
#Html.DropDownListFor(
Model => Model.answers[i].Name,
Pays(Model.answers[i].Value)
)
When that being done you should change your property "Pays" in the ViewModel to a method that accepts a value (idk what you're using, but let's assume it's string) - to something along the lines of this:
public IEnumerable<SelectListItem> Pays(string selectedValue)
{
if (_countries == null) SetCountries();
var value = new List<SelectListItem>();
foreach(var item in _countries)
{
item.Selected = (item.Value == selectedValue);
value.Add(item);
}
return value;
}
This above is a bit pseudocoded since I'm typing this from memory, but it should get you into the correct direction. Also remember to check with the inspect element in the browser if the dropdown HTML element really has the correct name attribute.
I want to use the list of state controller in a district controller. Are there any better ideas.
I have tried one which is working
I put this code in the district controller by using constructor injection.
In this case, the entire code needs to be placed in the district controller.
Is there any way to reduce the code. A better way?
#region StateDropDown
public List<SelectListItem> StateDropDown()
{
List<SelectListItem> selectListItem = new List<SelectListItem>();
List<StateViewModel> stateList = Mapper.Map<List<State>, List<StateViewModel>>(_stateBusiness.GetStateForSelectList());
if (stateList != null)
foreach (StateViewModel state in stateList)
{
selectListItem.Add(new SelectListItem
{
Text = state.Description,
Value = state.Code.ToString(),
Selected = false
});
}
return selectListItem;
}
#endregion StateDropDown
This is what the term 'reusability' is invented for. Place the code in another file and make calls to it from any number of controllers you want, like code below.
//StateBusiness.cs
public class StateBusiness
{
public List<SelectListItem> GetStatesForDropdown()
{
//your logic here
return new List<SelectListItem>();
}
}
//StateController.cs
public class StateController : Controller
{
var state = new StateBusiness();
public ActionResult Index()
{
//call your code here
var states = state.GetStatesForDropdown();
//and do whatever you want
ViewBag.states = states;
return View();
}
}
//DistrictController.cs
public class DistrictController : Controller
{
var state = new StateBusiness();
public ActionResult Index()
{
//call it from here just the same
var states = state.GetStatesForDropdown();
ViewBag.states = states;
return View();
}
}
I don't know about better, but you could shorten this considerably using linq Select.
Mapper.Map<List<State>, List<StateViewModel>>(_stateBusiness.GetStateForSelectList())?
.Select(state => new SelectListItem
{
Text = state.Description,
Value = state.Code.ToString(),
Selected = false
}))?.ToList() ?? List<SelectListItem>();
If you using core one option might be to keep this off the controller and use a TagHelper this will let you inject the options into the tag with a simple attribute state-items reducing controller dependencies and keeping this state off the ViewBag while being more reusable.
Here is how it wold look in the view:
<select asp-for="State" state-items />
The TagHelper:
[HtmlTargetElement("select", Attributes = "state-items")]
public class StateItemsTagHelper : TagHelper {
private readonly StateBusiness _stateBusiness;
[HtmlAttributeName("asp-for")]
public ModelExpression For { get; set; }
public StateItemsTagHelper(StateBusiness stateBusiness) {
this._stateBusiness = stateBusiness;
}
public override void Process(TagHelperContext context, TagHelperOutput output) {
content.TagMode = TagMode.StartTagAndEndTag;
var value = For?.Model as string;
var items = _stateBusiness.GetStateForSelectList()?.Select(state => new SelectListItem {
Text = state.Description,
Value = state.Code.ToString(),
Selected = value == state.Code.ToString()
})) ?? Enumerable.Empty<SelectListItem>();
foreach(var item in items) {
output.Content.AppendHtml(item.ToHtmlContent());
}
}
}
For reusability item.ToHtmlContent is an extension method:
public static IHtmlContent ToHtmlContent(this SelectListItem item) {
var option = new TagBuilder("option");
option.Attributes.Add("value", item.Value);
if(item.Selected) {
option.Attributes.Add("selected", "selected");
}
option.InnerHtml.Append(item.Text);
return option;
}
I have a list of incidents which can have associated jobs. I Have a separate views for incidents and jobs. From the incident index page I have the following link to create a new job for that incident:
#Html.ActionLink("Create","Create", "Job", new { id = item.IncidentID }, null)
which takes the incident ID from that field and loads the Job view. I want to pass the ID as a default value for creating a new job, so the job will be assigned the incident ID.
I made this controller:
public ActionResult Create(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var newid = id;
ViewBag.ActionCode = new SelectList(db.ActionTypes, "ActionCode", "ActionType1");
ViewBag.IncidentID = new SelectList(db.Incidents, "IncidentID", "DefectFreeText");
return View();
}
How can I assign a default value to the form on the create job view ? I thought something like this:
#Html.EditorFor(model => model.IncidentID, id/newid)
Can anyone help me figure out what I am doing wrong?
I am assuming you want to set a default item for your Incidents dropdown list when user pass that to your create action method as a querystring. I would avoid using ViewBag approach to transfer your dropdown list data to the view and switch to a strongly typed viewmodel approach.
First create a viewmodel for our create view.
public class CreateJobVM
{
public int IncidentID { set;get;}
public int ActionTypeID { set;get;}
public List<SelectListItem> ActionTypes { set;get;}
public List<SelectListItem> Incidents{ set;get;}
public CreateJobVM()
{
ActionTypes =new List<SelectListItem>();
Incidents=new List<SelectListItem>();
}
}
And in your GET view,
public ActionResult Create(int? id)
{
var vm=new CreateJobVM();
vm.ActionTypes=GetActionTypes();
vm.Incidents=GetIncidents();
if(id.HasValue)
{
//set the selected item here
vm.IncidentID =id.Value;
}
return View(vm);
}
Assuming GetActionTypes and GetIncidents method returns a list of SelectListItems, From a DB table/ XML /whatever place you have data
public List<SelectListItem> GetActionTypes()
{
List<SelectListItem> actionTypesList = new List<SelectListItem>();
actionTypesList = db.ActionTypes
.Select(s => new SelectListItem { Value = s.ID.ToString(),
Text = s.Name }).ToList();
return actionTypesList;
}
and in your view which is strongly typed to CreateJobVM
#model CreateJobVM
#using(Html.Beginform())
{
#Html.DropDownListFor(s=>s.ActionTypeID ,Model.ActionTypes)
#Html.DropDownListFor(s=>s.IncidentID,Model.Incidents)
<input type="submit" />
}
When you post the form you can check the property values to get the values user selected in the form
[HttpPost]
public ActionResult Create(CreateJobVM model)
{
//check for model.IncidentID, ActionTypeID
// to do : Save and redirect
}
Just pass it with the help of ViewBag/ViewData
ViewBag.DefaultId=id;
return View();
If you have a model based view
YourViewModel.DefaultId=id;
return View(YourViewModel);
In View,
#ViewBag.DefaultId
or with ViewModel
YourViewModel.DefaultId
Hi I have Dropdown in Index page where user needs to select lists. Values are coming from Database. I took this dropdown value into session so I can carry this to Httppost.
Below is my code in Index page :
var activitydropdown = orderdata.uspApp_ActivityPageReportname(Convert.ToInt32(newid)).ToList();
List<SelectListItem> activitypage = new List<SelectListItem>();
if (activitydropdown != null && activitydropdown.Count > 0)
{
foreach (var activityresults in activitydropdown)
{
activitypage.Add(new SelectListItem
{
Text = activityresults.name,
Value = activityresults.id.ToString(),
});
}
}
ViewData["activitydropdown"] = activitypage;
Session["activitydropdown"] = activitypage;
And this is my code in view :
#using (Html.BeginForm("Index", "Automation", new { step = "2" }, FormMethod.Post, new { id = "frmIndex" }))
{
#Html.DropDownList("DrpaActivity", ViewData["activitydropdown"] as List<SelectListItem>, "All", new { style = "margin-left:694px;margin-bottom:20px;", onchange = "submit();" })
Now when user selects list from dropdown, i need to carry that text to my httpost index. Now in httpost index, in debug mode if i see this code :
var sessionlistautomation = Session["activitydropdown"];
I can see text and value and selected is false for every item. So how can i carry text here selected from Index to httpost, so when user selects list from dropdown, it stores that text value.
It will be available in your Request i.e.
Request["DrpaActivity"]
However I would strongly advise using ViewModels instead as they're typesafe, less room for error and easier to use.
If you create a view model, like below:
public class AViewModel
{
public string DrpaActivity { get; set; }
public List<SelectListItem> ActivitySelectList { get; set; }
}
In your Index you can return it like this:
public ActionResult Index()
{
var model = new AViewModel();
// set the select list i.e.
model.ActivitySelectList = // get from db etc
return View(model);
}
Then in your view declare the model at the top
#model AViewModel
...
Set your dropdown like this:
#Html.DropDownListFor(m => m.DrpaActivity, Model.ActivitySelectList as List<SelectListItem>, "All", new { style = "margin-left:694px;margin-bottom:20px;", onchange = "submit();" })
You can then get your selected drop-down in your post as follows:
[HttpPost]
public ActionResult Index(AViewModel model)
{
var isValid = model.DrpaActivity;
return View(model);
}
I want to select the default value in drop down list where policyId = 7 but it didn't select that value, what i am doing wrong?
Controller:
var pm = new ManagerClass();
IEnumerable<myClass> po = pm.GetDataFromDb();
IEnumerable<SelectListItem> Policies = new SelectList(po, "PolicyID", "PolicyName", new { PolicyID = 7 });
ViewBag.Policies = Policies;
View:
#Html.DropDownListFor(m => m.PolicyID, ViewBag.Policies as IEnumerable<SelectListItem>, new { #class = "dropdown-field"})
It's because it's not actually selecting the value in the SelectList.
First, to make it nicer, put the items in your view model to prevent the cast (this is better practice too):
public class MyModel
{
public int PolicyID { get; set; }
public List<SelectListItem> Policies { get; set; }
//rest of your model
}
Then populate it:
var model = new MyModel();
model.Policies = po
.Select(p => new SelectListItem
{
Text = p.PolicyName,
Value = p.PolicyID.ToString(),
Selected = p.PolicyID == currentPolicyId //change that to whatever current is
})
.ToList();
Then in your view, do:
#Html.DropDownListFor(m => m.PolicyID, Model.Policies, new { #class = "dropdown-field"})
Just set the PolicyID property on your view model to the value you want to be preselected:
var pm = new ManagerClass();
var po = pm.GetDataFromDb();
ViewBag.Policies = new SelectList(po, "PolicyID", "PolicyName");
viewModel.PolicyID = 7;
return View(viewModel);
Since your DropDownList is bound to the PolicyID property (m => m.PolicyID), then its value will be used when deciding which element to be preselected.
In case that you have a static menu:
1- create the following class:
public static class StaticMenus
{
public static List<string> GetGridRowsCount()
{
List<string> result = new List<string>();
result.Add("3");
result.Add("5");
result.Add("10");
result.Add("20");
result.Add("25");
result.Add("50");
result.Add("100");
return result;
}
}
2- add the following code to your controller :
ViewData["CountryList"] = new SelectList(StaticMenus.GetGridRowsCount(),"10");
3- add the following code to your view:
#Html.DropDownList("MainGridRowsCount", ViewData["RowsCountList"] as SelectList)