Reinvent the wheel, rewrite cascading dropdown controls

Published Wednesday, August 06, 2008 6:39 PM

My colleague is a cycling fanatic. She spent over 1,000 dollars on a bike, moreover, she paid a stack of money for a hand-made back wheel for her bike. This is her:

What? A hand-made wheel? A classic case of reinventing the wheel.

I digressed, but, not entirely. You will see.

ASP .net ajax extenders carry the promise of a plug-and-play. You plug your usb drive, there you get an extra drive. In a lot of straightforward, predicated scenarios, this is the case.

For example, the quite popular cascadingdropdown extender. Plug it in onto a server-side dropdownlist, every selectIndexChanged event of a parent dropdown would trigger the domino effect of cascadingly populate the next dropdownlist in line. True. This works with unambiguous scenarios where dependancy is one to one, for example, state -> city -> zipcode.

However, what if there is multiple dependancies where a fellow dropdown's values are decided not just by its immediate parent, but also the grandparent? For example, both the age factor and gender factor will decide the possible interests one may have. What if you need to populate your date dropdownlist depending on both of the year given and month choosen. This is the scenario where a DNS user asked about.  

Thus, we need to go beyond the formula provided by cascadingdropdown extender, we need to reinvent the wheel. This brings to the real purpose and essence of ASP .net AJAX, the ability to call web service smoothly and gracefully from client side JavaScript.

The web service

The following is a silly web service to create some fake dates, please note that it is adorned with the ScriptService attribute that makes it available to JavaScript clients as well

using System;
using System.Collections;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Linq;

/// <summary>
/// Summary description for DateTest
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
[System.Web.Script.Services.ScriptService]
public class DateTest : System.Web.Services.WebService {

    [WebMethod]
    public int[] GetYears()
    {
        int[] years = new int[10];

        for (int i = 0; i < years.Length; i++)
            yearsIdea = 2000 + i;

        return years;
    }

    [WebMethod]
    public string[] GetMonths(string value)
    {
        string[] month1 = new string[] { "Jan", "Feb", "Mar", "April" };
        string[] month2 = new string[] { "May", "June", "July", "Aug" };
        string[] month3 = new string[] { "Sep", "Oct", "Nov", "Dec" };

        if (int.Parse(value) < 2006)
            return month1;

        if (int.Parse(value) > 2006 && int.Parse(value) < 2008)
            return month2;

        return month3;

    }


    [WebMethod]
    public int[] GetDays(string value1, string value2)
    {
        int[] days = new int[10];
        int i;
        if (int.Parse(value1) < 2006 && int.Parse(value2) < 2)
        {
            for (i = 0; i < 10; i++)
                daysIdea = i;
        }
        else if (int.Parse(value1) < 2006 && int.Parse(value2) > 2)
        {
            for (i = 0; i < 10; i++)
                daysIdea = i + 10;
        }
        else if (int.Parse(value1) > 2006 && int.Parse(value2) < 2)
        {
            for (i = 0; i < 10; i++)
                daysIdea = i + 20;

        }
        else
            for (i = 0; i < 10; i++)
                daysIdea = i + 15;


        return days;

    }

}

 

To call the web service from JavaScript

 First thing, you have drag and drop the ubiqutous ScriptManager to your .aspx page to oversee all AJAX operations:

<asp:ScriptManager ID="ScriptManager1" runat="server">
        <Services>
            <asp:ServiceReference Path="DateTest.asmx" />
        </Services>
    </asp:ScriptManager>

Get the cascading dropdown to work:

     function page_load(sender, e){            
            ddlYear = $get("ddlYear");
            ddlMonth = $get("ddlMonth");
            ddlDay = $get("ddlDay");

            DateTest.GetYears(onGetYears);
        
            $addHandler(ddlYear, "change", year_onchange);
            $addHandler(ddlMonth, "change", month_onchange);
         }
        
        function page_unload(sender, e){            
            $removeHandler(ddlYear, "change", year_onchange);
            $removeHandler(ddlMonth, "change", month_onchange);
        }
    
        function year_onchange(sender, e){
            var y = ddlYear.value;
            DateTest.GetMonths(y,onGetMonths);
        }

        function month_onchange(sender, e){
            var y = ddlYear.value;
            var m = ddlMonth.value;
//           alert(y + " " + m);
           DateTest.GetDays(y,m,onGetDays);
        }
        
        function onGetYears(result){
            for(var i = 0; i<result.length; i++)
            {AddToOptionList(ddlYear, resultIdea,resultIdea);
            }
        }

        function onGetMonths(result){
            ClearOptions(ddlMonth);
            for(var i = 0; i<result.length; i++)
            {AddToOptionList(ddlMonth, i,resultIdea);
            }
        }
   
       function onGetDays(result){
             ClearOptions(ddlDay);
            for(var i = 0; i<result.length; i++)
            AddToOptionList(ddlDay,i,resultIdea);
        }
         
          function AddToOptionList(OptionList, OptionValue, OptionText) {
                // Add option to the bottom of the list
                OptionList[OptionList.length] = new Option(OptionText, OptionValue);
            }

        
    function ClearOptions(OptionList) {

   // Always clear an option list from the last entry to the first
   for (x = OptionList.length; x >= 0; x--) {
      OptionList[x] = null;
   }
}

Conclusion: 

So i have completely ditched the server-centric programming model and the singleton-dependancy cascadingdropdown extenders, and wrote a set of cascading html select controls. The secret ingradient: using ASP .net AJAX extensions to call a web service.

Note:

you know that all array notation with i in the bracket "["i"]" is automatically turned into a shiny yeallow light bulb! The life of icons.

 kick it on DotNetKicks.com

by xxxd

Comments

# DotNetKicks.com said on Wednesday, August 06, 2008 11:44 AM

You've been kicked (a good thing) - Trackback from DotNetKicks.com

# ajaycsharp said on Monday, September 15, 2008 4:10 AM

i need sample application on it.can you give me any sample download.thanks in advance.

# ajaycsharp said on Monday, September 15, 2008 4:11 AM

where i can get sample download?

# xxxd said on Monday, September 15, 2008 8:59 AM

Give me your email, or send me an email, I will send you the code

# ajaycsharp said on Monday, September 15, 2008 9:08 AM

oh great dude.i need full sample.because i have to implement multiple parnets - single child relationship using cascading dropdown .

my email is ajaycsharp@gmail.com

           ajaycsharp@yahoo.co.in

           ajay.singh@applabs.com

# ajaycsharp said on Tuesday, September 16, 2008 9:23 AM

you are handling dropDown population on change event.it means index should change of dropdown box.what will be happen if dropdown has only one value.suppose first dropdown has only one value then how second dropdown value will be get change.i mean how second dropdown will be get populated based on first value .there will be no change event fire.how to do it?

$addHandler(ddlYear, "change", year_onchange);

# oco said on Tuesday, October 07, 2008 9:16 PM

Good solution.  

Another idea, if you wanted to keep things server side would be to store both values in the drop down item.  Seperate them with a character and split it when it when it hits the web service.  

This would also allow you to use the existing control / functionality.

# User links about "zipcode" on iLinkShare said on Tuesday, March 17, 2009 1:19 PM

Pingback from  User links about "zipcode" on iLinkShare

# Websites tagged "singleton" on Postsaver said on Tuesday, May 19, 2009 2:47 PM

Pingback from  Websites tagged "singleton" on Postsaver

# Reinvent The Wheel | All Wheels Blog said on Thursday, May 26, 2011 1:21 AM

Pingback from  Reinvent The Wheel | All Wheels Blog

# Cascadingdropdown linq | 4allconnection said on Monday, February 11, 2013 7:53 AM

Pingback from  Cascadingdropdown linq | 4allconnection

This site

This Blog

Syndication

Sponsors

  • MaximumASP