Saturday, November 27, 2021

How to select a default value in DropDownList from a database

 

‘Default’ and ‘Selected’ values - why do we need two?

There are two ways to specify which item is selected in a dropdown list, and this is the main source of confusion and problems. There are two distinct scenarios:

  1. The page is loaded for the first time and the dropdown selection is set to some default value, say ‘US’ for the country selection.
  2. The page is loaded with real data, and the dropdown selection is set to a value that user had chosen previously.

How to specify default value

Let’s say you have a class ‘Country’ with two properties, ‘Id’ and ‘Name’, and you want to display a dropdown list with the country selection, where Australia is pre-selected by default (because naturally, you expect that most of your users will be from Australia).

There are at least two ways you can do that: either by using a helper class SelectList which creates a collection of SelectListItem instances or by creating that collection manually in the controller.

Use SelectList in the view

This is the most simple and short way of doing that. Note how 13 is used to specify default selection.

@Html.DropDownListFor(
    m => m.CountryId, // Specifies where to store selected country Id
                      // It needs to be null for the default selection to work!

    new SelectList(Model.Countries, // IEnumerable<Country>, contains all countries loaded from a database
                   "Id",   // Use Country.Id as a data source for the values of dropdown items
                   "Name", // Use Country.Name as a data source for the text of dropdown items
                   13 // Specifies Australia (which has ID of 13) as the element selected by default
                   ),

    // Text of option that prompts user to select
    "- Please select your country -"
)

Use SelectListItem in the controller

This method is a bit more involved but it allows you use more complex logic for figuring which element should be marked as selected.

Controller code:

var allCountries = countryRepository.GetAllCountries();
var items = new List<SelectListItem>();

foreach(var country in allCountries)
{
    items.Add(new SelectListItem() {
        Text = coutry.Name,
        Value = Country.Id.ToString(),
        // Put all sorts of business logic in here
        Selected = country.Id == 13 ? true : false
    });
}

model.Countries = items;

And then in your view:

@Html.DropDownListFor(
    m => m.CountryId, // Specifies where to store selected country Id
                      // It needs to be null for the default selection to work!

    Model.Countries, // just supply already created collection of SelectListItems

    // Text of option that prompts user to select
    "- Please select your country -"
)

DANGER. WARNING. THERE BE DRAGONS.

There’s one BIG CAVEAT: the default value supplied via one of those methods will be completely ignored if the value of the first parameter of DropDownListFor (Model.CountryId in this case) is not null. In other words, if a user had selected a value or if the model got this value set via some other pathway (like you loaded it from a database), the default value will be ignored.

I have tripped over this myself, time and again, even when writing this article. So make sure the model field that you use to store the selected Id from the dropdown list is nullable and is set to null on the first page load.

Also, do not use SelectedList or SelectedListItem to specify what user had selected, instead use them for what they are built - to specify a default value.

How to specify selected value

Selected value is different from the default value in the way that it had, well, been selected at some point. You may have just loaded an object from a database for editing and need to render already selected country.

To do so you need to use the first argument of the DropDownListFor function. Also, note that whatever you specify in SelectList/SelectListItem constructors for selected value will be ignored.

Simplified controller code, which loads a user from a database, sets values on the model:

public EditUser(int userId) {
    var user = LoadUserFromDB(userId);
    var model = new UserModel();
    model.CountryId = user.CountryId;
    model.Countries = GetAllCountries();
    //... other code to set the rest of the properties
    return View(model);
}

View code, uses Model.ContryId to specify selected value:

@Html.DropDownListFor(
    m => m.CountryId, // Specifies where to store selected country Id
                      // It needs to be null for the default selection to work!

    new SelectList(Model.Countries,
                   "Id",
                   "Name"),

    // Text of option that prompts user to select
    "- Please select your country -"
)

Get complete, tested, and working source code for this article

Download fully tested and 100% working Visual Studio solution with the source code used in this article for FREE – just enter your name and email in the form below, and I’ll send you the download link right away.

You will also get access to all the source code for all existing and new articles on the site, and access to my mailing list, which receives handy timesaving tips on .NET Core programming.

No comments:

Post a Comment

No String Argument Constructor/Factory Method to Deserialize From String Value

  In this short article, we will cover in-depth the   JsonMappingException: no String-argument constructor/factory method to deserialize fro...