Add attribute to select list option

asp.net-mvc-3, html.dropdownlistfor, razor

Solution

Just getting back to this now. While @nikeaa's answer is certainly a viable solution I thought it was a bit heavyweight especially using XDocument. As a reminder what I'm dealing with is a TypeType (Cars) and SubType (list of car types - Viper, Granada, Hunter, Zodiac, Wolsley 1660, etc). TypeType could also be Trucks, Bicycles, etc. So here's how I solved it:

I added a JsonResult method on the Controller to return an anonymous object with the 3 properties that I wanted:

public class VehicleController : Controller
{
    // etc.
    public JsonResult GetSubTypesForTypeType(string typeTypeName)
    {
        var cars = pronova2Repository.GetTypeWithSubTypes(typeTypeName);

        return cars == null
        ? Json(new object[0], JsonRequestBehavior.AllowGet)
        : Json(cars.SubTypes.OrderBy(s => s.Name).Select(
            s => new { s.SubTypeID, s.Name, s.Description }).ToArray(),
            JsonRequestBehavior.AllowGet);
    }
    // etc.
}

Then in js:

Populate the drop down:

// populate the cars drop down when the select list is available
if ($('select#SubTypeID').length) {
    var carsSelect = $('select#SubTypeID');
    var carsList = populateCarsList("CARS");
    var carsListHtml = createCarsSelectList(carsList);
    carsSelect.html('');
    carsSelect.append(carsListHtml);

    $('#SubTypeID').change(function (e) {
        clearFormData();
    });
}

Call a function to get the subtypes (cars) via an ajax call:

function populateCarsList(typeTypeName) {
    var carsList;

    $.ajax({
        url: '/Vehicle/GetSubTypesForTypeType',
        data: { typeTypeName: typeTypeName },
        async: false
    }).done(function (data) {
        carsList = data;
    }).error(function (msg, url, line) {
        alert("Error retrieving cars from Vehicle/GetSubTypesForTypeType. Error message: " + line);
    });

    return carsList;
}

Function to create the select list with the added description as a "data-*" attribute:

function createCarsSelectList(selectData) {
    var html = '',
        len = selectData.length,
        selected,
        description;

    for (var i = 0; i < len; i++) {

        // "Viper" should be selected by default
        if (selectData[i].Name.toLocaleUpperCase() === "VIPER") {
            selected = ' selected="selected" ';
        } else {
            selected = '';
        }

        // Add the description (as a "data-" attribute), some descritions are null
        if (selectData[i].Description != null) {
            description = selectData[i].Description;
        } else {
            description = '';
        }

        html += '<option value="' + selectData[i].SubTypeID + '" data-description="' + description + '"' + selected + '>' + selectData[i].Name + '</option>';
    }

    return html;
}

Problem

I have a list of items in a drop down list within a Razor view. In the database each item has 3 values associated with it - the database id, short name (for display), and long name (for passing to a service). The drop down must show the short name, so I'm populating the drop down with the database id as the value and the short name as the text. However when a user selects an item I need pass the long name as a query parameter to a search service using jQuery, e.g when Cortina is seleted "Ford Cortina 1979 Blue" needs to be passed to the service. My first thought is store the long name as a data dash attribute but I'm wondering is there a better way. So - How do I store all 3 values in the drop down list? - If I do use data dash attributes how do I incorporate all the LONG_NAME values into Html.DropDownListFor or somehow add them to the drop down list? DB: ``` CARID SHORT_NAME LONG_NAME 1 Viper Dodge Viper 1982 2 Boxster Porsche Boxster 2009 Black 3 Cortina Ford Cortina 1979 Blue ``` Controller helper to create the drop down: ``` public static IEnumerable<SelectListItem> GetSelectList(this IEFRepository repository, string typeName) { var vehicle = repository.TypeTypes.FirstOrDefault(t => t.Name.ToUpper() == typeName); if (vehicle != null) { var carList = vehicle.SubTypes.ToList().OrderBy(s => s.Name); var selectList = new SelectList(subTypeList, "SubTypeID", "Name"); return selectList; } } ``` Here's the code I use to create the drop down: ``` <div class="editor-field"> @Html.DropDownListFor(model => model.CarID, new SelectList(ViewBag.Cars, "Value", "Text", "1")) @Html.ValidationMessageFor(model => model.CarShortName) </div> ``` Here's the output: ``` <select id="CarID" name="CarID" data-val="true" data-val-number="The field CarID must be a number." data-val-required="The CarID field is required."> <option value="2">Boxster</option> <option value="3">Cortina</option> <option selected="selected" value="1">Viper</option> </select> ```

Original source