I'm trying to use SelectListItem for an MVC project, drop down is populated as I expect it. But when I pass the selected value to a function that accepts string using this model.CodeDropDown.ToString() I get System.Collections.Generic.List 1[System.Web.Mvc.SelectListItem] which is not a string.
How can I get the selected value as string?
I have a ViewModel class that looks like this:
public class HomeViewModel
{
[Required]
[DisplayName("Code")]
public IEnumerable<SelectListItem> CodeDropDown { get; set; }
public string SelectedValue { get; set; }
}
I'm filling up the dropdown using this Controller
public ActionResult Index()
{
var model = new HomeViewModel();
using (var dbCon = new SomeDBContext())
{
model.CodeDropDown = dbCon.CodeID.ToList().Select(x => new SelectListItem
{
Value = x.Name.ToString(), Text = x.CodeDropDown.ToString()
}).DistinctBy(c => c.Value);
}
return View(model);
}
}
I'm trying to use the value from SelectListItem like this,
public ActionResult Index(HomeViewModel model)
{
var results = mainDbContext.GetSomeResult(model.CodeDropDown.ToString(), model.Prop2, model.Prop3);
return View(results);
}
View looks like this:
#Html.DropDownListFor(model => model.SelectedValue, Model.CodeDropDown, "--")
Add one more property (SelectedThingId or something more meaningful) to your HomeViewModel to hold the value of the selected thing from the dropdown.
In your view (you have not posted code for view) have something like this:
#Html.DropDownListFor(x=>x.SelectedThingId, Model.CodeDropDown)
Then in your controller you can get this value using:
model.SelectedThingId; // model is passed into your controller has you have it.
Add 2 properties in the model
public string CodedropdownID{ get; set; } //to store the selected dropdown value Id
public string CodedropdownText{ get; set; } //to store the selected dropdown value text
Change the View as following and add onchange event to dropdown:
#Html.DropDownListFor(m=> m.CodedropdownID, m.CodeDropDown, "--")
#Html.Hiddenfor(m=>m.CodedropdownText)
Add the following script:
<script type="text/javascript">
$("#CodedropdownID").on("change", function {
$("#CodedropdownText").val($(this).text());
});
</script>
Change the controller method
public ActionResult Index(HomeViewModel model)
{
var results = mainDbContext.GetSomeResult(model.CodedropdownText.ToString(), model.Prop2, model.Prop3);
return View(results);
}
Related
The scenario is:
Data is stored in database in project and neighbourhood tables both.
Now, i want to populate dropdown with project id and project name and neighbourhoodId and neighbourhood name.
i am right now sending through viewBag like this:
ViewBag.NeighbourhoodId = new SelectList(allNeighbourhood(), "Id", "NeighbourhoodName");
on view page, getting dropdown populated like this:
#Html.DropDownList("Locations", ViewBag.NeighbourhoodId as SelectList, "Select a location")
Now,how to send another viewBag in this dropdownList.
Second ques, My dropdown is in partial view So, i am sending data to partial view like this:
#Html.Partial("_CommentBoxSection",new Neighbourhood())
how to send new Project()) along with neighbourhood. Is there any overload of partial where i can send both of them.
i have seen some posts relating to this title but they are something different
I have recently tried this:
public class ProjectAndNeighbourhoodListItemViewModel
{
public Project Project { get; set; }
public Neighbourhood Neighbourhood { get; set; }
public string ProjectName { get; set; }
public int Id { get; set; }
public bool IsSelected { get; set; }
// public IEnumerable<SelectListItem> ToSelectListItem { get; set; }
public SelectListItem ToSelectListItem()
{
return new SelectListItem
{
Text = Project.ProjectName,
Value = Neighbourhood.Id.ToString(),
Selected = IsSelected
};
}
}
and on view page directly,
#model #model IEnumerable<ProjectAndNeighbourhoodListItemViewModel>
#Html.DropDownList("Locations", Model.Select(m => m.ToSelectListItem()), "Select a location")
but getting System.ArgumentNullException value cannot be null i have no code in controller do i have to pass something in controller too
Do not use ViewBag to pass values to your view, use ViewModels instead, it is much cleaner. The ViewModel is also a good place to create your SelectListItems. Create or map the ViewModel in your controller.
// ViewModel for a single selectable entry
public class ProjectAndNeighbourhoodListItemViewModel {
public string ProjectName { get; set; }
public long NeighbourhoodId { get; set; }
public bool IsSelected { get; set; }
public SelectListItem ToSelectListItem() {
return new SelectListItem {
Text = ProjectName,
Value = NeighbourhoodId.ToString(),
Selected = IsSelected
}
}
}
In your Razor View:
#model IEnumerable<ProjectAndNeighbourhoodListItemViewModel>
#* Would be even better to use a wrapper model that contains the collection of list items as property! *#
#Html.DropDownList("Locations", Model.Select(m => m.ToSelectListItem()) , "Select a location")
I have two classes many-to-many the first is "Anuncios" and the second "SubCategorias"
public class Anuncios {
public int AnuncioId {get;set;}
public string Titulo {get;set;}
public ICollection<SubCategorias> SubCategorias {get;set;}
}
public class SubCategorias {
public int SubCategoriaId {get;set;}
public string Nome {get;set;}
public ICollection<Anuncios> Anuncios {get;set;}
}
In DAL layer I did method to save the "Anuncio" in DB.
public void Salvar(Anuncio entidade) {
entidade.SubCategorias = entidade.SubCategorias.Select(subcat => _contexto.SubCategorias.FirstOrDefault(x => x.SubCategoriaId == subcat.SubCategoriaId)).ToList();
_contexto.Anuncios.Add(entidade);
_contexto.SaveChanges();
}
I Create the Action "Create":
private readonly Context _ctx = new Context();
public ActionResult Create()
{
var model = new Anuncios {SubCategorias = _ctx.SubCategorias.ToList()};
return View(model);
}
In View I made DropDownList with "SubCategorias":
#Html.LabelFor(model => model.SubCategorias)
#Html.DropDownListFor(model => model.SubCategorias, new SelectList(Model.SubCategorias, "SubCategoriaId", "Nome"))
The DropDownListFor is populated with sucess..
Fine....
But when submit form the value selected in DropDownListFor not pass to method Create. The anuncio.SubCategorias is null!
private readonly AnunciosDal _anuncio = new AnunciosDal();
[HttpPost]
public ActionResult Create(Anuncio anuncio)
{
_anuncio.Salvar(anuncio);
return View(anuncio);
}
I have sought in various forums the solution, but could not find
Somebody help me?!
Sorry about my english rs...
Thank You!
FabrÃcio Oliveira
The first parameter of DropDownListFor needs to be the object holding the selected value, where the second parameter contains the list:
#Html.DropDownListFor(model => model.SOME_ID_FOR_SELECTED_VALUE,
new SelectList(Model.SubCategorias, "SubCategoriaId", "Nome"))
Currently the example you have also maps the same list as the first property. You should use an ID like #Maess suggested, and then bind it via:
#Html.DropDownListFor(model => model.SubCategoriaID, new SelectList(Model.SubCategorias, "SubCategoriaId", "Nome"))
Selecting a value will then post it back to the server to this SubCategoriaID field.
You need to have another property to store the selected value from the dropdown. It is best if you create a viewmodel with properties which are needed for your view.
public class CreateAnuncios
{
public string Title {set;get;}
public int SelectedSubCategoryId {set;get;}
public List<SelectListItem> SubCategories {set;get;}
public CreateAnuncios()
{
this.SubCategories = new List<SelectListItem>();
}
}
Now in your create action, create an object of this view model, Fill the SubCategories property and send to the view.
public ActionResult Create()
{
var vm=new CreateAnuncios();
vm.SubCategories = ctx.SubCategorias
.Select(s=> new SelectListItem
{ Value = s.SubCategoriaId .ToString(),
Text=s.Nome}).ToList();
return View(vm);
}
Your create view should be strongly typed to the CreateAnuncios class
#model YourNameSpaceHere.CreateAnuncios
#using(Html.Beginform())
{
#Html.TextBoxFor(s=>s.Title)
#Html.DropdownListFor(s=>s.SelectedSubCategoryId,Model.SubCategories,"Select")
<input type="submit" />
}
Now when user posts the form, Read the Properties of the posted model and use that to save to db.
[HttpPost]
public ActionResult Create(CreateAnuncios model)
{
//Check for model.Title and model.SelectedSubCategoryId and use it to save
// to do :Save and redirect
}
You need to provide a collection of SelectListItems that populate your DropDownList as well as a property to hold the currently selected SelectListItems' Id (which will be posted back to the server):
public class Anuncios {
public int AnuncioId {get;set;}
public string Titulo {get;set;}
public ICollection<SubCategorias> SubCategorias {get;set;}
public int SelectedSubCategoryId {get;set;}
public IEnumerable<SelectListItem> SubCategoryListItems {get;set;}
}
then, present them to the user via:
#html.DropDownListfor(x => x.SelectedSubCategoryId, Model.SubCategoryListItems)
The SubCategoryListItems will have to be populated from the server, typically something like this:
this.SubCategoryListItems = this.SubCategorias.Select(x => new SelectListItem { Text = x.Name, Value = x.Id });
You need an id property for the SubCategoria you have it in your binding, but not in the model
public class Anuncios {
public int AnuncioId {get;set;}
public string Titulo {get;set;}
public ICollection<SubCategorias> SubCategorias {get;set;}
public int SubCategoriaId{get;set;}
}
I've been following some guidance for a listbox and trying to handle the selections properly. What is stumping me and I can't seem to find relevant material on is accessing the value(s) selected. There may be only one selected but most likely there will be multiple selected at a time.
my post controller is getting the object model and it has the value of one of the selected items but not all of them? Do I need to run some jquery before the post as other articles have said? Doesn't seem right but maybe...
My model:
public partial class ExtrnlSubsModel : BaseEntityModel
{
public IList<SelectListItem> AvailableForums { get; set; }
public int ExtForumId { get; set; }
}
My razor:
#Html.ListBoxFor(model => model.ExtForumId, Model.AvailableForums, new { style = "width:500px;height:250px" })
#Html.RequiredHint()
#Html.ValidationMessageFor(model => model.ExtForumId)
My controller:
[HttpPost]
public ActionResult ExtForumAdd(ExtrnlSubsModel model)
{ .... }
So as I mentioned my model gets populated but only with a single selection despite having ctrl-clicked numerous items.
TIA
Change your model to use a MultiSelect and an array of ints for the selected items like this (partial removed for simplicity):
public class ExtrnlSubsModel
{
public MultiSelectList AvailableForums { get; set; }
public int[] ExtForumIds { get; set; }
}
Change your list box to this, with your array of ints property first:
#Html.ListBoxFor(model => model.ExtForumIds, Model.AvailableForums, new { style = "width:500px;height:250px" })
For test purposes a controller get action:
public ActionResult Index()
{
var items = new List<SelectItem>();
// These items would be set from your db
var items = new List<SelectItem>();
items.Add(new SelectItem { Id = 1, Name = "1" });
items.Add(new SelectItem { Id = 2, Name = "2" });
var selectedItems = new List<SelectItem>();
selectedItems.Add(new SelectItem { Id = 1, Name = "1" });
var model = new ExtrnlSubsModel();
// project the selected indexs to an array of ints
int[] selectedItemsArray = selectedItems.Select(s => s.Id).ToArray();
model.ExtForumIds = selectedItemsArray;
model.AvailableForums = new MultiSelectList(items, "ID", "Name", selectedItemsArray);
return View(model);
}
Post action:
[HttpPost]
public ActionResult Index(ExtrnlSubsModel model)
{
var selectedItems = model.ExtForumIds;
return View(model);
}
I have also used a test SelectItem for demo, this would be the object that you are returning instead:
public class SelectItem
{
public int Id { get; set; }
public string Name { get; set; }
}
Picture of the selected items posted back below:
I have a custom view model like this:
namespace MyCustomNamespace.Models
{
public class CustomViewModel
{
public CustomViewModel()
{
FirstViewModel = new FirstModel ();
SecondViewModel = new SecondModel ();
}
public FirstModel FirstViewModel { get; set; }
public SecondModel SecondViewModel { get; set; }
}
}
namespace MyCustomNamespace.Models
{
public class FirstModel
{
public string id { get; set; }
public string text { get; set; }
public IEnumerable<SelectListItem> Items
{
(...)
}
(...)
}
}
SecondModel is similar to FirstModel.
in my view i do using razor:
#model MyCustomNamespace.Models.CustomViewModel
(...)
#Html.DropDownListFor(m => m.FirstViewModel.Id, Model.FirstViewModel.Items)
(...)
I populate the dropdownlist with a model.
I am trying to know which is the current selected element in the dropdownlist shown above, but i do not know how.... maybe through the model? but how?
Updated:
This is my real model type, above was an example about what i was doing. FirstModel would be ComponentTypeModel in this case:
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System;
using Resources;
namespace MyCustomNamespace.Models
{
public class ComponentTypeModel
{
private readonly List<ComponentType> componentTypes;
public ComponentTypeModel()
{
using (ConfigContext dbContext = new ConfigContext())
{
try
{
componentTypes = dbContext.ComponentTypes.ToList();
}
catch (Exception ex)
{
//EventLogger.LogException(ex);
}
}
}
[Display(Name = "Component Type")]
public int SelectedCompTypeId { get; set; }
public IEnumerable<SelectListItem> CompTypeItems
{
get
{
var allCompTypes = componentTypes.Select(f => new SelectListItem
{
Value = f.ComponentTypeId.ToString(),
Text = f.Name
});
return DefaultCompTypeItem.Concat(allCompTypes);
}
}
public IEnumerable<SelectListItem> DefaultCompTypeItem
{
get
{
return Enumerable.Repeat(new SelectListItem
{
Value = "-1",
Text = "Select a component type"
},
count: 1);
}
}
}
}
In your models, you are using
public IEnumerable<SelectListItem> Items
{
(...)
}
That is fine, but doing so, you need to set manually the selected item. I suggest you to use a SelectList instead of a list of SelectListItems.
So, in your ViewModel, you need:
public SelectList Items {get; set;}
In your controller you populate that SelectList:
var myItems = GetMyCollectionOfItems(); //The list to display in the DropDownList
model.FirstViewModel.Items = new SelectList(myItems, "NameOfValueField", "NameOfTextField", selectedValue); //The selected value is optional
Then in your View you use:
#Html.DropDownListFor(m => m.FirstViewModel.Id, Model.FirstViewModel.Items, "--- Select Item---", new { #id = "firstModelID" })
Check that is the same code you used, but this way, is the SelectList who knows which item is selected and you don't need to do nothing manually. Just load the id of the select items in the SelectList constructor.
Then, if you need to know in client side which is the selected item, in order to use it in Javascript to hide something or something like that, you can do what the other people answers:
$( document ).ready(function() {
var mySelectedValue = $('#firstModelID').val();
alert(mySelectedValue);
});
If you need to know when the select value changes:
$( document ).ready(function() {
$('#firstModelID').change(function() {
alert($('#firstModelID').val());
});
});
AFTER YOUR UPDATE:
All the code you have in the Model, can be greatly simplified using the code in this answer.
You should do a little change: Make the
[Display(Name = "Component Type")]
public int SelectedCompTypeId { get; set; }
[Display(Name = "Component Type")]
public int? SelectedCompTypeId { get; set; } //Now this is nullable
If you do this way, you don't need to add the default item thing... just use:
#Html.DropDownListFor(m => m.FirstViewModel.Id, Model.FirstViewModel.Items, "Select a component type", new { #id = "firstModelID" })
Then in your controller, you can see it is Null you do the equivalent a what you do when you received the "-1".
Now, all the database access should be away of the model. The model is much cleaner this way:
public class ComponentTypeModel
{
[Display(Name = "Component Type")]
public int? SelectedCompTypeId { get; set; }
public SelectLis CompTypeItems { get; set:}
}
Then in your controller you do:
var model = new ComponentTypeModel();
model.CompTypeItems = new SelectList(dbContext.ComponentTypes.Select(x => x.Name, x.ComponentTypeId), "ComponentTypeId", "Name");
If you want to have one of them selected by default (as you usually do in an Edit view), you do this:
var model = new ComponentTypeModel();
model.CompTypeItems = new SelectList(dbContext.ComponentTypes.Select(x => x.Name, x.ComponentTypeId), "ComponentTypeId", "Name", myDefaultValue); //where the myDefaultValue is an int
The razor code in your view should remain the same, since all the information about selected item, collection of items, fields to be mapped remains in the controller and model.
If you trying to know it before submitting the form (on client side)
#Html.DropDownListFor(m => m.FirstViewModel.Id, Model.FirstViewModel.Items, "--- Select Item---", new { #id = "firstModelID" })
and you could check its value by: $('#firstModelID').val();
There's no way to identify that in C# on the client side, you'd have to use jQuery/JavaScript for that, something like:
$("#FirstViewModel_Id").val();
var Id = $("#FirstViewModel_Id").val();
alert(Id);
In addition to the answers here, you can also do like this:
$("#FirstViewModel_Id option:selected").val();
The selected value will be in the Id property of the posted model (FirstViewModel) after a post to the server.
You can access the
If you want to get the selected value on the client you can use:
$("#FirstViewModel_Id").val();
or
$("#FirstViewModel_Id option:selected").val();
if the first one doesn't work.
I have a model:
public class DocumentModel
{
public int TypeID { get; set; }
public List<SelectListItem> DocumentTypes { get; set; }
}
I have a view:
#Html.DropDownListFor(x => x.TypeID, Model.DocumentTypes, "- please select -")
I populate my drop down
var model = new DocumentModel();
model.DocumentTypes = GetDocumentTypes();
private static List<SelectListItem> GetDocumentTypes()
{
var items = new List<SelectListItem>
{
new SelectListItem
{Text = #"Text #1", Value = "1"},
new SelectListItem
{Text = #"Text #2", Value = "2"},
};
return items;
}
I have a controller action when the form is posted back:
[HttpPost]
public void UploadDocument(DocumentModel model)
{
if (ModelState.IsValid)
{
// I want to get the text from the dropdown
}
}
How do i get the text from my drop down list? Thanks
You may not get this easily with the default model binding. You have to a small workaround like this.
1) Add a new property to your model/viewmodel to store the selected text
public class DocumentModel
{
public int TypeID { get; set; }
public List<SelectListItem> DocumentTypes { get; set; }
public string SelctedType { set;get;}
}
2) Use Html.HiddenFor Helper method to create a hidden variable in the form for this property
#Html.HiddenFor(x => x.SelctedType)
3) Use little javascript to override the submit ! ie; When user submits the form, Get the selected Text from the dropdown and set that value as the value of the Hidden field.
$(function () {
$("form").submit(function(){
var selTypeText= $("#TypeID option:selected").text();
$("#SelctedType").val(selTypeText);
});
});
Now in your HTTPPost action method, This will be available in the SelectedType property.
[HttpPost]
public void UploadDocument(DocumentModel model)
{
if(ModelState.IsValid)
{
string thatValue=model.SelectedType;
}
}
if what you want to do is to retrieve selected item then this can do the work :
var selecteItem = model.DocumentTypes.Where(item=>item.Selected).FirstOrDefault();
Cheers!
On your model I would have another string -
public string Selected{ get; set; }
then in your view :
#Html.DropDownListFor(model => model.Selected, new SelectList(Model.DocumentTypes, "Value", "Text"))
I stumbled here trying to find the way to get the text value out of a SelectList to display it in a format other than a DropDownList (I'm reusing my Edit ViewModel as it has all the data I required)
var text = selectList.Where(q => q.Selected == true).First().Text;