Cascading DropDownLists - jQuery

This page is part of the Class Library Pages collection.
Click the icon to see the index.

Table of Contents [Hide/Show]


   Supporting Classes
      DropDownService Class
         VB.NET
         C#
   ASPX Host Page
      HTML Markup
      ASPX Code-Behind
         VB.NET
         C#
      JavaScript Code
   Service Code
      ASPX Markup
      Code-Behind
         VB.NET
         C#

{outline||<1> - |.<1> - }

Supporting Classes

DropDownService Class

VB.NET

Imports Microsoft.VisualBasic
Imports System.Data

Public Class DropDownService
    Inherits System.Web.UI.Page

    Protected _selectedValue As String
    Protected _fcn As String

    '----------------------------------------------------------------------------------------------
    Public Overridable Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load

        _fcn = Request.QueryString("fcn")
        _selectedValue = Request("sv")

        If _selectedValue Is Nothing OrElse _selectedValue.Length = 0 Then
            _selectedValue = "0"
        End If

    End Sub
    '----------------------------------------------------------------------------------------------
    Protected Function DropDownHtml(ByVal sourceTable As DataTable, ByVal textField As _
    String, ByVal valueField As String) As String

        Dim result As String = ""

        result &= DropDownItemHtml("--Select One--", "", _selectedValue)

        For Each row As DataRow In sourceTable.Rows

            result &= DropDownItemHtml(row.Item(textField).ToString(), _
                                        row.Item(valueField).ToString(), _
                                        _selectedValue)
        Next

        Return result

    End Function
    '----------------------------------------------------------------------------------------------
    Private Function DropDownItemHtml(ByVal text As String, ByVal value As String, ByVal _
    selectedValue As String) As String

        Dim result As String = ""

        result &= "<option value='"
        result &= value
        result &= "' "
        If value = selectedValue Then
            result &= "selected='true' "
        End If
        result &= ">"
        result &= text
        result &= "</option>"
        result &= vbCrLf

        Return result

    End Function

End Class

C#

TODO

ASPX Host Page

HTML Markup

Within the <%@ Page %> directive...
<%@ Page ... EnableEventValidation="false" ... %>

Within the <head> section...
<script type="text/javascript" src="Scripts/jquery.js"></script>
<script type="text/javascript" src="Scripts/MyPage.js"></script>

Within the <body> section...
<span id="ChannelDropDown">
    <asp:DropDownList ID="uxChannelDropDown" runat="server" />
    <br />
    <asp:HiddenField Value="0" ID="uxChannelField" runat="server" />
</span>


<span id="ReasonDropDown">
    <asp:DropDownList runat="server" ID="uxReasonDropDown" />
    <br />
    <asp:HiddenField Value="0" ID="uxReasonField" runat="server" />
</span>

ASPX Code-Behind

Note

Despite online postings to the contrary, the following code does NOT eliminate the Invalid postback or callback argument error. Instead, you must alter the <%@ Page %> directive as indicated above. Although this is a security risk, it is the only way I've found that resolves this issue.

VB.NET

Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)

    ClientScript.RegisterForEventValidation(uxChannelDropDown.UniqueID.ToString())
    ClientScript.RegisterForEventValidation(uxReasonDropDown.UniqueID.ToString())
    MyBase.Render(writer)

End Sub

C#

TODO


JavaScript Code

This code is in a separate javascript file that is loaded via a <script> tag.

//- Document Ready Function -----------------------------------------------------------------------
var uxDropDown1;
var uxDropDown2;

uxDropDown1 = "span#ChannelDropDown>select";
uxField1    = "span#ChannelDropDown>input";

uxDropDown2 = "span#ReasonDropDown>select";
uxField2    = "span#ReasonDropDown>input";

$(document).ready(function() 
{ 
	LoadPrimaryDropDown();	
	$(uxDropDown1).click(uxDropDown1_Change);
	$(uxDropDown2).click(uxDropDown2_Change);
});

//- Load Categories Drop Down List ----------------------------------------------------------------
function LoadPrimaryDropDown()
{
	$.get("ServiceWrapper.aspx", 
	        {    fcn:   "GetChannelsHtml"
	            ,sv:    $(uxField1).val()
	            },
	        function(data)
	        {
	            $(uxDropDown1).html(data);
	            uxDropDown1_Change();
	        }); 
}
//- Channel Drop Down Change Event Handler --------------------------------------------------------
function uxDropDown1_Change()
{
    // retain new value for when we refresh after a postback
    $(uxField1).val($(uxDropDown1).val());
    
    // cascade: the selected category filters the available topics
	$.get("ServiceWrapper.aspx", 
	        {    fcn:   "GetReasonsHtml"
	            ,sv:    $(uxField2).val()
	            ,cid:   $(uxDropDown1).val()
	            },
	        function(data)
	        {
	            $(uxDropDown2).html(data);
	            uxDropDown2_Change();
	        }); 
	        
}
//- Reason Drop-Down Change Event Handler ---------------------------------------------------------
function uxDropDown2_Change()
{
    $(uxField2).val($(uxDropDown2).val());
}

Service Code

This is the ASPX markup and code-behind file for the ServiceWrapper.ASPX page, which is called asynchronously by the JavaScript code above to populate the drop-downs. Note that this is NOT a web service page, but an ASPX page!

ASPX Markup

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="ServiceWrapper.aspx.vb" Inherits="ServiceWrapper" %>

Code-Behind

VB.NET

Imports System.Collections.Generic
Imports System.Data

Partial Class ServiceWrapper
    Inherits DropDownService

    Private _channelId As String

    '----------------------------------------------------------------------------------------------
    Public Overrides Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load

        MyBase.Page_Load(sender, e)

        If Not Integer.TryParse(Request("cid"), _channelId) Then
            _channelId = 0
        End If

        Select Case _fcn
            Case "GetChannelsHtml"
                Response.Write(GetChannelsHtml())
            Case "GetReasonsHtml"
                Response.Write(GetReasonsHtml())
        End Select

        Response.End()

    End Sub
    '----------------------------------------------------------------------------------------------
    Private Function GetChannelsHtml() As String

        Dim nvc As NameValueCollection = New NameValueCollection()
        nvc.Add("ReqType", "IPR")
        Dim formVerId As Integer = Databases.OnlineForms.GetFormVersionId(nvc)
        Dim t As DataTable = Databases.OnlineForms.GetFormSelectionOption(formVerId, "Channel")
        Return MyBase.DropDownHtml(t, "AttributeText", "AttributeID")

    End Function
    '----------------------------------------------------------------------------------------------
    Private Function GetReasonsHtml() As String

        Dim nvc As NameValueCollection = New NameValueCollection()
        nvc.Add("ReqType", "IPR")
        Dim formVerId As Integer = Databases.OnlineForms.GetFormVersionId(nvc)

        Dim t As DataTable = Databases.OnlineForms.GetFormSelectionOptionByParent( _
                                                            formVerId, "Reason", _channelId)

        Return MyBase.DropDownHtml(t, "AttributeText", "AttributeID")

    End Function

End Class

C#

TODO