Set an ASP.NET DropDownList's selected value or text with JavaScript and jQuery
An ASP.NET DropDownList renders as a plain <select>. Selecting an item from script means either setting the select's value or marking one <option> as selected. Both are easy; the traps are matching by text, triggering AutoPostBack, and the server's rules about which values it accepts back.
Sample control
<asp:DropDownList ID="ddlCountry" runat="server">
<asp:ListItem Value="" Text="-- choose --" />
<asp:ListItem Value="BE" Text="Belgium" />
<asp:ListItem Value="CA" Text="Canada" />
<asp:ListItem Value="FR" Text="France" />
<asp:ListItem Value="JP" Text="Japan" />
</asp:DropDownList>
Each ListItem becomes <option value="FR">France</option>. If you omit Value, ASP.NET uses the text as the value.
Plain JavaScript
By value
var ddl = document.getElementById("<%= ddlCountry.ClientID %>");
ddl.value = "FR"; // selects France
if (ddl.value !== "FR") {
// no option has that value; the browser leaves nothing selected (value === "")
}
Assigning a value that matches no option leaves the select with no selection (selectedIndex becomes -1) in current browsers, so check the result if the value comes from elsewhere.
By visible text
function selectByText(select, text) {
for (var i = 0; i < select.options.length; i++) {
if (select.options[i].text.trim() === text) {
select.selectedIndex = i;
return true;
}
}
return false;
}
selectByText(ddl, "Japan");
By position
ddl.selectedIndex = 0; // back to "-- choose --"
Reading back
var value = ddl.value;
var text = ddl.selectedIndex >= 0 ? ddl.options[ddl.selectedIndex].text : "";
jQuery
var $ddl = $("#<%= ddlCountry.ClientID %>");
// by value
$ddl.val("CA");
// by text (exact match, not "contains")
$ddl.find("option").filter(function () {
return $(this).text().trim() === "Belgium";
}).prop("selected", true);
// read
var value = $ddl.val();
var text = $ddl.find("option:selected").text();
Avoid the :contains() selector for this job: option:contains('Japan') would also match "Japanese yen" in another list, and it is case-sensitive. A filter with an exact comparison is predictable.
Firing change and AutoPostBack
Changing the selection from script does not raise the change event. If the list has AutoPostBack="true", ASP.NET renders an inline onchange handler that calls __doPostBack, and that handler will not run unless you raise the event:
// plain JavaScript
ddl.value = "FR";
ddl.dispatchEvent(new Event("change", { bubbles: true }));
// jQuery: trigger() also runs inline on-handlers
$ddl.val("FR").trigger("change");
On the server, SelectedIndexChanged fires during the postback because the posted value differs from the one in view state.
A working page
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Country.aspx.cs" Inherits="Demo.Country" %>
<!DOCTYPE html>
<html>
<head runat="server"><title>Country</title></head>
<body>
<form id="form1" runat="server">
<asp:DropDownList ID="ddlCountry" runat="server" AutoPostBack="true"
OnSelectedIndexChanged="ddlCountry_SelectedIndexChanged">
<asp:ListItem Value="" Text="-- choose --" />
<asp:ListItem Value="BE" Text="Belgium" />
<asp:ListItem Value="CA" Text="Canada" />
<asp:ListItem Value="FR" Text="France" />
<asp:ListItem Value="JP" Text="Japan" />
</asp:DropDownList>
<button type="button" id="pickJapan">Pick Japan</button>
<p><asp:Label ID="lblChoice" runat="server" /></p>
</form>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"
integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo="
crossorigin="anonymous"></script>
<script>
$("#pickJapan").on("click", function () {
$("#<%= ddlCountry.ClientID %>").val("JP").trigger("change");
});
</script>
</body>
</html>
using System;
using System.Web.UI;
namespace Demo
{
public partial class Country : Page
{
protected void ddlCountry_SelectedIndexChanged(object sender, EventArgs e)
{
lblChoice.Text = ddlCountry.SelectedValue == ""
? "No country selected."
: "You chose " + Server.HtmlEncode(ddlCountry.SelectedItem.Text) + ".";
}
}
}
Setting the selection on the server
The same operations in C#, for completeness:
// by value: throws ArgumentOutOfRangeException if no item has that value
ddlCountry.SelectedValue = "FR";
// by text: clear first, or ASP.NET may throw
// "Cannot have multiple items selected in a DropDownList."
ddlCountry.ClearSelection();
ListItem item = ddlCountry.Items.FindByText("Canada");
if (item != null)
{
item.Selected = true;
}
The "multiple items selected" error happens when code sets Selected = true on one item while another item is already selected. ClearSelection() avoids it. Setting SelectedValue or SelectedIndex clears the previous selection for you.
If you set SelectedValue before the list is data-bound (for example before DataBind()), ASP.NET stores the value and applies it after binding; if the value is still missing at that point, the exception is thrown then.
Options added in the browser
Selecting an existing option from script is always accepted. Adding a new <option> on the client and posting it is not: with event validation on (the default), the server compares the posted value with the values it rendered and throws "Invalid postback or callback argument". Options that change in the browser should come from the server, for example through a postback or an UpdatePanel, as in the cascading country, state and city lists. Turning off EnableEventValidation to make the error disappear removes a useful protection; if you really need client-built lists, read the value from Request.Form and validate it yourself.
Reading the current selection is covered in Get the selected value or text with JavaScript and with jQuery.
Common mistakes
- Selecting before the list exists. If the list is filled by an
UpdatePanelor an AJAX call, settingvalueright after the page loads does nothing because the option is not there yet. Run the selection after the list has been filled, for example in the success callback. - Comparing text with different white space or case. Option texts rendered from data may contain trailing spaces. Trim both sides, and compare with
toLowerCase()if case should not matter. - Using
attr("selected", "selected"). Changing the attribute changes the default selection, not necessarily the current one in every browser. Use.val()or.prop("selected", true). - Forgetting the server. A selection made in the browser is just a posted value. The server must still check that it is allowed for this user, especially when the list is filtered by permissions.
- Several lists with the same id. Inside a GridView or Repeater, select relative to the row (
$(this).closest("tr").find("select")) instead of building ids by hand.
Official documentation
- Microsoft Learn: DropDownList class, ListControl.SelectedValue, ListControl.ClearSelection()
- MDN: HTMLSelectElement (
value,selectedIndex,options) - jQuery API: .val(), .filter(), .trigger()