I'd like to post back to the server when my combobox changes value (ideally with an AJAX call in an update panel - but one thing at a time). I'm using the I'm using the jQuery UI AutoComplete Combobox and, unfortunately, it's interferring with the change event as I'm not changing the drop down list directly.

I'm using the implementation detailed here.

Here are some choice snippets

HTML Body Code

<!-- language: lang-html -->
<span class="ui-widget">
    <asp:DropDownList ID="cboLang" runat="server" AutoPostBack="True">
        <asp:ListItem Value="ActionScript">ActionScript</asp:ListItem>
        <asp:ListItem Value="AppleScript">AppleScript</asp:ListItem>
        <asp:ListItem Value="Asp">Asp</asp:ListItem>
    </asp:DropDownList>
</span>

Autocomplete Javascript

This is the autocomplete js that exexutes whenever a selection has been made. It will always run the function _removeIfInvalid

<!-- language: lang-js -->
this._on(this.input, {
	autocompleteselect: function (event, ui) {
		ui.item.option.selected = true;
		this._trigger("select", event, {
			item: ui.item.option
		});
	},

	autocompletechange: "_removeIfInvalid"
});

Server Side Code

<!-- language: lang-vb -->
Protected Sub cboLang_SelectedIndexChanged(sender As Object, e As EventArgs) _
        Handles cboLang.SelectedIndexChanged
    'DO OTHER STUFF HERE
    Dim alert = String.Format("alert('{0}');", "Hi")
    ScriptManager.RegisterStartupScript(Me, Me.GetType, "DropDownChange", alert, True)
End Sub

Generated Code

When an ASP.NET renders the page with the attached event, it produces the following code

<!-- language: lang-html -->
<script type="text/javascript">
//<![CDATA[
var theForm = document.forms['ctl00'];
if (!theForm) {
    theForm = document.ctl00;
}
function __doPostBack(eventTarget, eventArgument) {
    if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
        theForm.__EVENTTARGET.value = eventTarget;
        theForm.__EVENTARGUMENT.value = eventArgument;
    theForm.submit();
    }
}
//]]>
</script>

<select id="cboLang" onchange="javascript:setTimeout('__doPostBack(\'cboLang\',\'\')', 0)"
    name="cboLang" style="display: none;">

Question

Where can I go about making changes to ensure that with each update to the autcomplete input, I can trigger a server event?

There are a couple things that are helpful for answering this question. One is to take a look at JQuery-UI's own documentation on this function:

<!-- language: lang-js -->
// Initialize the autocomplete with the select callback specified:
$( ".selector" ).autocomplete({  select: function( event, ui ) {}}); 
// Bind an event listener to the autocompleteselect event:
$( ".selector" ).on( "autocompleteselect", function( event, ui ) {} ); 

Essentially, what needs to happen, is something needs to signal a callback when the item has been selected (either from the menu or by typing and getting an exact match).

We can do this by modifying the default functionality demonstrated on the autocomplete page:

<!-- language: lang-js -->
this._on( this.input, {
  autocompleteselect: function( event, ui ) {
    ui.item.option.selected = true;
    this._trigger( "select", event, {
      item: ui.item.option
    });
  },
  autocompletechange: "_removeIfInvalid"
});

This code attaches listeneres on the select and change events and runs the inline defined function and the _removeIfInvalid function whenever those events fire (respectively)

By implementing the following changes we can do a postback when a valid selection has been made:

<!-- language: lang-js -->
//attach listeners
this._on(this.input, {
  autocompleteselect: "_selectFromMenu",
  autocompletechange: "_removeIfInvalid"
});

Will get called anytime an item is selected from the menu:

<!-- language: lang-js -->
_selectFromMenu: function (event, ui) {
  ui.item.option.selected = true;
  this._trigger("select", event, {
      item: ui.item.option
    });
  __doPostBack('', '');
},

Will get called any time the text changes:

<!-- language: lang-js -->
_removeIfInvalid: function (event, ui) {

  // Selected an item, automatically valid, post back
  if (ui.item) {
    __doPostBack('', '');
    return;
  }

  // Search for a match (case-insensitive)
  var value = this.input.val(),
    valueLowerCase = value.toLowerCase(),
    valid = false;
  this.element.children("option").each(function () {
      if ($(this).text().toLowerCase() === valueLowerCase) {
        this.selected = valid = true;
        return false;
      }
    });

  // Found a match, post back
  if (valid) {
    __doPostBack('', '');
    return;
  }

  // Remove invalid value...

Here's a jsfiddle with the complete code changes, although __doPostBack is commented out because it is not being handled by anything

A couple further note:

  • I'm calling __doPostBack, but I'm relying on that method being available because of asp.net event handling generated code.
  • In order to initialize the combo box, you have to call $("#combobox").combobox();. Make sure that whatever is preforming that operation is still getting called on the return from the post back, otherwise the functionality will not come back. This is one thing to work past if you're using the code asynchronously in an update panel.