Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set ASP MVC form dropdown to blank but only if the underlying value is uninitialised?

We have a plain ASP.NET MVC form with lots of fields. The first field is the most important, and it's a dropdown list. Let's say it's the company field and it contains two value "Coca Cola" and "Pepsi".

The company field looks like this:

    <div class="editor-label">
       @Html.LabelFor(Function(model) model.Company)
    </div>
    <div class="editor-field">
        @Html.DropDownListFor(Function(model) model.Company, TryCast(ViewData("Companies"), SelectList), New With {Key .style = "blah blah;"})
        @Html.ValidationMessageFor(Function(model) model.Company)
    </div>

Because it's important this choice is actively made and is not simply left on "Coca Cola" simply because it's first alphabetically, we need the field to be empty first of all (validation data annotations take care of forcing the user to put something in).

This is easily done with Javascript like so:

        function InitialiseForm() {
            $('#Company').prop('selectedIndex', -1);
        }

        window.onload = InitialiseForm;

However, we have a few cases where the form isn't loaded entirely blank, and instead the company field is initialised in the controller, like so:

    modelObject.Company = "Coca Cola" 

and in such cases we of course don't want the Javascript to execute and erase this.

What's the normal solution in such cases?

like image 745
hawbsl Avatar asked Oct 16 '13 13:10

hawbsl


3 Answers

My supposition was correct: the DropDownListFor doesn't generate the selected attribute if the initial value is null.

With empty company it generates the following html:

<select id="Company" name="Company">
   <option value="1">Coca-Cola</option>
   <option value="2">Pepsi</option>
</select>

With selected company html code is different:

<select id="Company" name="Company">
   <option selected="selected" value="1">Coca-Cola</option>
   <option value="2">Pepsi</option>
</select>

So you can use this javascript code and it will work:

$(function () {
    if ($("#Company").find("option[selected]").length == 0) {
        $("#Company").prop('selectedIndex', -1);
    }
});

Also if your jquery version is earlier than 1.9.0, the option[selected] expression may not work properly. The bug is fixed in 1.9.0, but in earlier versions functions like 'filter', 'children' and 'is' worked incorrectly, whereas 'find' and 'has' returned a correct result.

like image 110
vortexwolf Avatar answered Nov 15 '22 16:11

vortexwolf


I faced a similar issue a few days ago, wanting to default my dropdown to the first index, unless it was selected at some point. I used a session variable as a remedy...something like this might do the trick:

var CurrentCompanyID = 1;
var gCompanyID = '@(Convert.ToInt32(Session["CompanyID"]))';

if (gCompanyID == null || gCompanyID == '' || gCompanyID == 0) {
    CurrentCompanyID = 1;
}
else {
    CurrentCompanyID = gCompanyID;
    $("#CompanyDropDown").val(CurrentCompanyID);
}

$("#CompanyDropDown").change(function () {
    CurrentCompanyID = $(this).val();

    $.ajax({
        url: "Controller/ChangeCompany",
        cache: false,
        data: { _compID: CurrentCompanyID },
        success: function (result) {
            console.log(result);
            $("#CompanyForm").submit();
        }
    });
});

// Where:

public JsonResult ChangeCompany(int _compID)
{
    Session["CompanyID"] = _compID;
    return Json(Session["CompanyID"], JsonRequestBehavior.AllowGet);
}

...and for the Index() action of the current controller:

var _compID = Convert.ToInt32(Session["CompanyID"]);
var dataContext = new SERVERDataContext();

if (Session["CompanyID"] == null)
{
    //Get Companies

    return View(vm);
}
else
{
    //Get Companies where Company.ID == _compID

    return View(vm);
}

So essentially I'm setting the current value of the dropdown to the session variable's value. If I want to change the dropdown value, I simply assign a new value to the session var! While the session var is null or worthless, set the dropdown to my desired index.

Hope this helps.

like image 30
Mike H. Avatar answered Nov 15 '22 15:11

Mike H.


here's one clean way to do that :

Add an optional label to the list, it will be selected if the model company value is empty, otherwise the current value will be shown preselected (no need for the javaScript select code), also if the user dont choose a value he can't pass the validation :

@Html.DropDownListFor(Function(model) model.Company, TryCast(ViewData("Companies"), SelectList), "Select a company", New With {Key .style = "blah blah;"})
like image 22
Chtiwi Malek Avatar answered Nov 15 '22 16:11

Chtiwi Malek