Recently I had a scenario where I needed to pass a value to a web service when a user selected an option in a drop down list. I had the drop down in a Razor view and when an item was selected an associated value needed to be passed to a web service as a parameter. However the value to be passed was not the id or value in the drop down but a different value associated with the selected item. So I needed a way to store this associated value in the drop down along with each displayed item.

In the database each item had 3 values associated with it – the database id, short name (for display), and long name (for passing to a service). The drop down needed to show the short name, so I populated the drop down with the database id as the value and the short name as the text.

As an example the drop down had values such as Cortina, Boxster, and Viper. When Cortina is seleted “Ford Cortina 1979 Blue” needed to be passed to the service. The solution I came up with was to store the long name as a data dash attribute in each item in the drop down. So here’s the data:

CARID SHORT_NAME LONG_NAME
1     Viper     Dodge Viper 1982
2     Boxster   Porsche Boxster 2009 Black
3     Cortina   Ford Cortina 1979 Blue

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 = repository.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.
}

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>

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 - 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 &lt; 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 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;
}
Advertisements