Multiple DropDownLists from Dictionary (KVP) in model - c#

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>

Related

Select Option dropdown not displaying selected option

I have a Blazor app that populates 6 select option dropdowns with data from DB. Three of these are populated with date and time from a string list.
When I select a date and time it is not displayed in the dropdown box. After selecting a date time the dropdown is blank, but the value is actually selected and binding works. It's just not displayed.
If I remove "bind=#..." it displays correctly.
Have anyone else experienced this, and how did you solve it?
<select bind="#Innput.Klokkeslett1">
<option value="#(0)">Tid1</option>
#foreach (var tid1 in tidListe)
{
<option value="#tid1">#tid1</option>
}
</select>
Two things to note, select uses a string value, and that value needs to match the option value.
So, if your field Innput.Klokkeslett1 is a DateTime, you will need to use a property to handle the binding / conversion between string and DateTime.
If you ensure you use an explicit date format for the option values, and your property returns it's value in the same date format, then the select will be able to match it's value to one of it's option values and display the corresponding text, which can be formatted any way you like.
<select bind="#MySelectProxy">
<option value="#(0)">Tid1</option>
#foreach (var tid1 in tidListe)
{
<option value="#tid1.ToString("yyyy-MM-dd HH:mm:ss")">#tid1</option>
}
</select>
#functions
{
string MySelectProxy {
get => Innput.Klokkeslett1.ToString("yyyy-MM-dd HH:mm:ss");
set => DateTime.TryParse(value, out Innput.Klokkeslett1);
}
}
<select onchange="#ComboSelectionChanged">
<option value="0" selected>
#list[0]
</option>
#for (int i = 1; i < list.Count; i++)
{
<option value="#i">
#list[i]
</option>
}
</select>
public void ComboSelectionChanged(UIChangeEventArgs e)
{
if (int.TryParse(e.Value.ToString(), out int index))
{
SelectedStyleIndex = index
//now you know which one is selected
}
}

Send id to controller from view in option tag

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){}

Populate dropdownlist from a value

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

Best way to get selected option in drop down list from model

I'm wondering what the best practice is to select an option from a select field from my database.
I am pulling the data in from my model, but it seems like having an if in every line of code isnt the most efficient.
Here is my current code, is there a better way?
<select id="Downloads" name="Downloads">
<option value="Option1" <% if(Model.Downloads == "Option1"){ %>selected <% } %>>Option1</option>
<option value="Option2" <% if(Model.Downloads == "Option2"){ %>selected <% } %>>Option2</option>
<option value="Option3" <% if(Model.Downloads == "Option3"){ %>selected <% } %>>Option3</option>
</select>
I have 10 of these select boxes and just want to keep my code clean
Build a SelectList, or a collection of SelectListItems on your model, and then use use DropdownListFor:
#Html.DropDownListFor(x => x.Downloads, Model.DownloadOptions)
I suggest you add a css class to each select box.Then create an javascript array to save value of them. Following is a way to retrieve value of them and push them into javascript array.
var values =[];
$(".mySelectBox").each(function(i) {
//push to values array
});

How to bind an array to multiple dropdown lists?

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.

Categories