.NET Core <select> With Default Value?
Asked Answered
T

3

11

My goal is to generate a <select> dropdown with a certain select value (<option>) pre-selected, so the finalized HTML should look like this:

<select>
  <option value = "1">Option1</option>
  <option value = "2" selected>Option2</option>
  <option value = "3">Option3</option>
</select>

Note that the option with a value of 2 has a selected attribute, indicating that it will show before the dropdown is clicked. I cannot (and am trying to) achieve this using .NET Core Tag Helpers.

This is my model (I think you can safely ignore the details):

public class ReportViewModel
{
  [Display(Name = "Pick a form")]
  public IEnumerable<Form> AvailableForms { get; set; }

  public Form SelectedForm { get; set; }

  public List<ReportData> FormResponses { get; set; }
}

Note that the Form object there just has Id and Name properties on it.

This is my select statement:

<label asp-for="SelectedForm.Name" class="form-control-label font-weight-bold"></label>
<select asp-for="SelectedForm.Name"
        class="form-control"
        onchange ="onFormSelected(this.value)"
        asp-items="@(new SelectList(Model.AvailableForms, "Id", "Name"))">
</select>

I don't see the answer in the Microsoft Guide Or in a blog on the topic

Thimble answered 13/12, 2017 at 15:46 Comment(4)
Is this for a default "empty" state or are you trying to display a selected value (such as user preference which has been chosen already)?Echols
@Echols The user picks a form on another page. This page (with the markup) above then gets loaded. The purpose is so they can pick another form for a report if they want to. So, in short, I have the id of the "default" form in the controller before the view loads.Thimble
The asp-for value will determine what is initially selected.Carnage
Thanks @CalC, trying that now. I was before, assumed that was the case.Thimble
K
7

Basically you need to is set the select to use the SelectedForm.Id property, then specify the value of the form to be selected in your controller. I had to update your code a little but this works for me -

<label asp-for="SelectedForm" class="form-control-label font-weight-bold"></label>
<select asp-for="SelectedForm.Id"
        class="form-control"
        onchange ="onFormSelected(this.value)"
        asp-items="@(new SelectList(Model.AvailableForms, "Id", "Name"))">
</select>

Then in your controller

var vm = new ReportViewModel()
{
    AvailableForms = new List<Form>()
};

var form2 = new Form() { Id = 2, Name = "Bar" };
(vm.AvailableForms as List<Form>).Add(new Form() { Id = 1, Name = "Foo" });
(vm.AvailableForms as List<Form>).Add(form2);
(vm.AvailableForms as List<Form>).Add(new Form() { Id = 3, Name = "Baz" });

vm.SelectedForm = form2;

return View(vm);
Kasey answered 13/12, 2017 at 16:16 Comment(1)
Asp.net core will bind the attribute of asp-for,Cupric
L
3

The SelectList constructor can take an additional argument, namely selectedValue. In your case, you should be able to pass this through, which I think will look something like this:

asp-items="@(new SelectList(Model.AvailableForms, "Id", "Name", Model.SelectedForm.Id))"

I think the reason asp-for isn't working for you is the mismatch between the value of SelectedForm.Name (which is a string), and the value of the Id property you're using in the SelectList constructor (which is an integer?).

You can see partially how this works in the source code. You end up here in GenerateOption:

var selected = item.Selected;
if (currentValues != null)
{
    var value = item.Value ?? item.Text;
    selected = currentValues.Contains(value);
}

At this point, I believe currentValues will contain a single element, which will be a string (Form.Name). I believe also that item.Value will be e.g. "1" and so there's no match.

Lambskin answered 13/12, 2017 at 17:13 Comment(0)
R
-3

This is old, but I didn't see my approach here. Pass it in with a viewbag from the controller.

<select>
    <option>@ViewBag.selected</option>
    <option>1</option>
    <option>2</option>
    <option>3</option>
</select>
Relative answered 23/10, 2020 at 0:30 Comment(2)
Haha, maybe in another 3 years, I will get to use Razor again and try this out and upvote it.Thimble
If my selected value is 2, this now adds the options of 2,1,2,3. It makes it confusing to users that there are now duplicates in the list. How do you remove the duplicate?Arrogance

© 2022 - 2024 — McMap. All rights reserved.