My model contains an array of items:
public class MyModel
{
public IEnumerable<ListItem> AllItems { get; set; }
public string[] SelectedItems { get; set; }
}
I understand it's simple enough to create a single multi-select drop-down list and render it with Razor, but my list of items is pretty long and multi-selecting does not make for a good UI experience (too easy to lose selections).
I would rather have separate dropdown for each item. This is easy enough to manage with HTML / JS, but I am wondering what my element IDs should be for the model binding in MVC to work on submit.
Thanks!
Update
What I want to end up with is the something similar to this HTML, where I would have one list per selected item, with ability to add a new item or remove existing one:
<select>
<option value="1" selected>blah</option>
...
<option value="15">blah</option>
...
<option value="xx">[ remove this item ]</option>
</select>
<select>
<option value="1">blah</option>
...
<option value="15" selected>blah</option>
...
<option value="xx">[ remove this item ]</option>
</select>
<button>Add another</button>
I hope that clears my question up a bit.
Related
I am trying to create my first web app. I have list of products and I want to sort products by name or price. The possible option I have in <select> tag and I try to use method onchange to send paramteres to my controller and there sort my list of products. When I debug my program I saw that as paramteres is send null value. Have you got some idea how can I resolve my problem?
<p>Sort by:</p>
<select onchange="location = this.value">
<option value="#Url.Action("SortByString", new { id = "-----" })">-----</option>
<option value="#Url.Action("SortByString", new { id = "Name" })">Name</option>
<option value="#Url.Action("SortByString", new { id = "Price" })">Price</option>
</select>
public ActionResult SortByString(string sort){}
And as paramter sort is send null. Thanks.
You should use one of the multiple overloads of Url.Action() method according to your need. In this case, you can use the fourth overload which is specified in this article.
So you need to change your code as following to pass exactly that parameter which you specified in your action method in the controller (If you don't want to define a custom route for your URL):
<p>Sort by:</p>
<select onchange="location = this.value">
<option value="#Url.Action("SortByString", new { sort = "-----" })">-----</option>
<option value="#Url.Action("SortByString", new { sort = "Name" })">Name</option>
<option value="#Url.Action("SortByString", new { sort = "Price" })">Price</option>
</select>
public ActionResult SortByString(string sort){}
I am trying to dynamically create multiple dropdownlists (ASP.Net MVC project) for a user to map columns for importing data from a CSV file. I get the list of columns from the CSV file, and place them in a SelectList. These are the SourceColumns from which the user chooses for each destination.
If I hard-code the destination indexes, it works fine. What I mean by this is, if I add an integer property for every destination index.
However, I need to create this dynamically, so I added a Dictionary to my model to hold the destination names and the selected source indexes. The destinations are just key value pairs (IDictionary<string key, int? value>) where value is the index of the source column.
However, with the dictionary I cannot work out how to get the values back to my controller. They keys come back with null values. Maybe this is not possible with the Html helpers, but any suggestions welcome.
Model
public class ProductionImportModel
{
public IDictionary<string, int ?> ColumnIndices { get; set; }
// plus other properties
}
Controller
model.ColumnIndices.Add("Line", null);
View
#foreach (var kvp in #Model.ColumnIndices)
{
#Html.DropDownList("Model.ColumnIndices[" + #kvp.Key + "].Key", (SelectList)ViewBag.SourceColumns, String.Empty, null)
}
Resulting HTML
<select id="Model_ColumnIndices_Line__Key" name="Model.ColumnIndices[Line].Key">
<option value=""></option>
<option value="0">Col1</option>
<option value="1">Col2</option>
<option value="2">Col3</option>
</select>
The solution was a minor change to my view. I was not providing the correct information for the model binder. I used the DropDownListFor() helper instead of DropDownList().
Revised View
#foreach (var kvp in #Model.ColumnIndices)
{
#Html.DropDownListFor(m => #Model.ColumnIndices[#kvp.Key], (SelectList)ViewBag.SourceColumns, String.Empty, null)
}
This meant that the resulting HTML looked like this
<select id="ColumnIndices_Line_" name="ColumnIndices[Line]">
<option value=""></option>
<option value="0">Col1</option>
<option value="1">Col2</option>
<option value="2">Col3</option>
</select>
I have a drop down list which contains 3 values:
Male
Female
Unspecified
Basically in my view, when I selected with male, female or unspecified, I want to change the data that I have in another combo box, e.g. the male users, the female users and the users who haven't given their gender.
List<User> users = new List<User>();
foreach (User user in ctspc.db.AllUsers.ToList())
{
users.Add(DAL.Getusers(user.UserId));
}
So here I get all the users, my problem is I need to use LINQ to sort out which type of gender I need to search, that bit I can handle, the problem I am having is that I am unable to retrieve the drop down list value.
I tried:
var x = Request.Params["cboGender"];
But I assume because the page hasn't loaded yet, it isn't able to get what the current value is, so basically what I am trying to do is have it so depending on the value in the list box at the time, I want it to recall my Create method and keep getting the selected value and updating the new list box.
Here I have the cshtml code
<select name="cboGender">
#foreach (var Gender in ViewBag.Genders)
{
<option value="#Gender.GenderId">#Gender.Name</option>
}
</select>
<select name="cboUser">
#foreach (var User in ViewBag.UsersByGender)
{
<option value="#User.UserId">#User.Username</option>
}
</select>
Any help on how I can do this would be great.
If I understand your problem correctly then, you can try one of the following methods to retrieve data.
e.g.
public ActionResult SomeAction(string cboGender)
or try using
string Gender= Request.QueryString["cboGender"];
or
[HttpPost]
public ActionResult SubmitAction(FormCollection collection)
{
// Get Post Params Here
string var1 = collection["cboGender"];
}
there is no other way to do this without js.
Oh, maybe you can create a button to sumbit the form,so your server side can get the value,
Request.Params["cboGender"] will effective. then filter user,render the page(it means refresh and bad experience ), is that your want?
I guess you used to do with asp.net WebForm.
In fact , WebForm framework also encapsulated with much js(JQuery) code.
the best way is : use ajax to post the genderId to server method like belowe
[HttpPost]
public JsonResult GetUserByGenderId(int? genderId)
{
var list = AllUsers.Where(a => a.genderId == genderId);// filter user
return Json(list);// return serialized json or
return Json(list.Select(a=>new { a.UserName,a.UserId }).Tolist());
}
and the ajax would receive this json to render the cboUser.
There are lots of ways to do this, but based on the way you've asked the question I think the easiest would be to do something along these lines:
1: Put a new combo-box into the page for each group of users, and hide them by default (note here I'm not a foreach like you are but that's just for brevity of the example):
<select id="cboGender" name="cboGender">
<option id="Male">Male</option>
<option id="Female">Female</option>
<option id="Unspecified">Unspecified</option>
</select>
<select id="cboMale" class="user-combo" name="user" hidden>
<option id="1">Oscar</option>
<option id="2">Leo</option>
</select>
<select id="cboFemale" class="user-combo" name="user" hidden>
<option id="3">Kristy</option>
<option id="4">Wendy</option>
</select>
<select id="cboUnspecified" class="user-combo" name="user" hidden>
<option id="5">Jamie</option>
<option id="6">Charlie</option>
</select>
2: Use jQuery to listen for changes to the "cboGender" combo box, then show the appropriate combo box in response:
var onGenderChanged = function() {
var gender = $genders.val();
// Hide all gender combo boxes...
$userCombos.hide();
// ... then show the one corresponding to the selection
$("#cbo" + gender).show();
};
Here's a JSBin which shows a working implementation.
The advantage of doing this is it saves you a "round-trip" to get the gender specific users each time the user changes.
Another alternative would be to load the users with an AJAX request when a gender is selected, but that's a bit more involved.
HTH
I have an list of objects that I receive in my Razor View in C#
#model IEnumerable<Project.Models.EvaluationObject>
In each object of the IEnumerable I have a property called "MaxValue" that I want to put selected in a input select of html.
foreach(var item in Model){
<select>
<option value=1>One</option>
<option value=2>Two</option>
<option value=3>Three</option>
<option value=4>Four</option>
</select>
}
For each item I want to build a select input with the value of the item.MaxValue selected
i.e. In the first loop item.MaxValue = 3, then I should build the next select:
<select>
<option value=1>One</option>
<option value=2>Two</option>
<option value=3 selected="selected">Three</option>
<option value=4>Four</option>
</select>
The item.MaxValue is ever between 1 and 4, so If the value is 3 the selected value in the select input is 3.
The First solution I had, is to put an if statement in each option, but I think that's impractrical:
foreach(var item in Model){
<select>
<option value=1 #if(item.MaxValue==1){<text>selected="selected"</text>})>One</option>
<option value=2 #if(item.MaxValue==2){<text>selected="selected"</text>}>Two</option>
<option value=3 #if(item.MaxValue==3){<text>selected="selected"</text>}>Three</option>
<option value=4 #if(item.MaxValue==4){<text>selected="selected"</text>}>Four</option>
</select>
}
Hope you can help me, May be I should use some JavaScript.
You can add a IEnumerable<SelectListItem> to your model:
Model:
public class EvaluationObject
{
public IEnumerable<SelectListItem> EvaluationList
{
get
{
return Enumerable.Range(1, 4)
.Select(x => new SelectListItem
{
Selected = x == MaxValue,
Text = NumberToWord(x),
Value = x
});
}
}
public int MaxValue { get; set; }
public int EvaluationNumber { get; set; }
}
View:
foreach (var item in Model)
{
#Html.DropDownListFor(x => x.EvaluationNumber, item.EvaluationList)
}
i am using this demo:
http://www.emblematiq.com/lab/niceforms/demo/v20/niceforms.html
i would like to know which values the user has selected.
<select size="4" name="languages[]" id="languages" multiple="multiple">
<option value="English">English</option>
<option value="French">French</option>
<option value="Spanish">Spanish</option>
<option value="Italian">Italian</option>
<option value="Chinese">Chinese</option>
<option value="Japanese">Japanese</option>
<option value="Russian">Russian</option>
<option value="Esperanto">Esperanto</option>
</select>
the question is how do i return the values that were selected by the user?
I've put together a quick demo (using the select box structure from your example) here: http://jsfiddle.net/wp7sq/
So essentially, in my example I've created a simple function that gets which options the user selected, adds them to an array (just for convenience). So from here, you can output it to a string, or search your array, or do whatever you want using JavaScript using that array.
The relevant section is commented in the sample, and here's the jQuery code from my example:
var selectedLanguages = new Array();
jQuery('#languages option:selected').each(function() {
selectedLanguages.push(jQuery(this).val());
});
Try something like this:
ob = document.getElementById('languages');
for (var i = 0; i < ob.options.length; i++){
if (ob.options[ i ].selected){
alert(ob.options[ i ].value); //Do something useful here
}
}
$("#languages").value;should work