Showing posts sorted by relevance for query OPTGROUP. Sort by date Show all posts
Showing posts sorted by relevance for query OPTGROUP. Sort by date Show all posts

ASP.NET DropdownList with <optgroup>

If you are looking for an easy and simplest solution to create groups in the ASP.NET DropdownList control without writing unnecessary amount of backend code, then you are at the right place. Let me show you how we can do this using JQuery 1.2.6.

I have divided the solution into two different parts. First part explains achieving the desired output using JQuery's native support for wrapping elements into other elements with the help of wrapAll() method. It takes only 1 line of code and we can have the groups created in the HTML. However, the drawback of this approach is the groups will disappear on postback. But if the DropdownList is small and we are not loading it from the database, then this approach is very suitable as it will save a lot of time and effort.

Ok, enough of the riff-raff and get down to business now.

Part 01 (static binding of list items with no support for postback)

Step 01: Creating a DropdownList

ListItemCollection list = new ListItemCollection();

list.Add(new ListItem("1", "1"));
list.Add(new ListItem("2", "2"));
list.Add(new ListItem("3", "3"));
list.Add(new ListItem("4", "4"));
list.Add(new ListItem("5", "5"));
list.Add(new ListItem("6", "6"));
list.Add(new ListItem("7", "7"));
list.Add(new ListItem("8", "8"));
list.Add(new ListItem("9", "9"));
list.Add(new ListItem("10", "10"));

ddl.DataSource = list;
ddl.DataBind();

Step 02: Creating a new attribute
We have to create a new attribute for every DropdownList item. This new attribute will be used for grouping in the JQuery code.

protected void ddl_DataBound(object sender, EventArgs e)
{
foreach (ListItem item in ((DropDownList)sender).Items)
{
if (System.Int32.Parse(item.Value) < 5)
item.Attributes.Add("classification", "LessThanFive");
else
item.Attributes.Add("classification", "GreaterThanFive");
}

}

Step 03: The fun part - Creating groups using JQuery WrapAll() method

<script>
$(document).ready(function() {
//Create groups for dropdown list
$("select.listsmall option[@classification='LessThanFive']").wrapAll("<optgroup label='Less than five'>");
$("select.listsmall option[@classification='GreaterThanFive']").wrapAll("<optgroup label='Greater than five'>");
});

</script>


Part 02 (dynamic binding of list items with full support for postback)

This approach not only creates groups using JQuery 1.2.6 but also allows DropdownList to remember these groups across postbacks. We will have to create a custom server control using DropdownList class and override SaveViewState() and LoadViewState() methods that will help the page ViewState remember and restore groups respectively.

As mentioned earlier, in this approach we have to create a custom server control with a bit of a backend code and override some of it's important methods. However, if you are one of those lazy developers like me who don't like the idea of creating controls specially custom server controls that reside in a separate assembly for a very tiny job such as the one in hand, then you can create control that is part of the same assembly by adding a new class file and deriving it's class from System.Web.UI.WebControls.DropDownList.


namespace ControlLibrary
{
public class DropdownList : System.Web.UI.WebControls.DropDownList
{
protected override object SaveViewState()
{
// Create an object array with one element for the CheckBoxList's
// ViewState contents, and one element for each ListItem in skmCheckBoxList
object[] state = new object[this.Items.Count + 1];

object baseState = base.SaveViewState();
state[0] = baseState;

// Now, see if we even need to save the view state
bool itemHasAttributes = false;
for (int i = 0; i < this.Items.Count; i++)
{
if (this.Items[i].Attributes.Count > 0)
{
itemHasAttributes = true;

// Create an array of the item's Attribute's keys and values
object[] attribKV = new object[this.Items[i].Attributes.Count * 2];
int k = 0;
foreach (string key in this.Items[i].Attributes.Keys)
{
attribKV[k++] = key;
attribKV[k++] = this.Items[i].Attributes[key];
}

state[i + 1] = attribKV;
}
}

// return either baseState or state, depending on whether or not
// any ListItems had attributes
if (itemHasAttributes)
return state;
else
return baseState;

}

protected override void LoadViewState(object savedState)
{
if (savedState == null) return;

// see if savedState is an object or object array
if (savedState is object[])
{
// we have an array of items with attributes
object [] state = (object[]) savedState;
base.LoadViewState(state[0]); // load the base state

for (int i = 1; i < state.Length; i++)
{
if (state[i] != null)
{
// Load back in the attributes
object [] attribKV = (object[]) state[i];
for (int k = 0; k < attribKV.Length; k += 2)
this.Items[i-1].Attributes.Add(attribKV[k].ToString(),
attribKV[k+1].ToString());
}
}
}
else
// we have just the base state
base.LoadViewState(savedState);
}
}
}

If you search on the internet for a solution to create <optgroup> in ASP.NET DropdownList, you will find some of the articles talking about overriding RenderContents() method of DropdownList to create . However, I personally feel that this job can also be done with less of a hassle using JQuery WrapAll() method that wraps elements inside other elements. All we need is to have a mechanism to have these groups saved upon postbacks which we are doing here by overriding SaveVeiwState() and LoadViewState() as Scott Mitchell describes in his article. Apart from these 2 methods, we need to populate the DropdownList in Page_Load method and create a new attribute in the ddl_DataBound() event as explained in the part 01 above. That is all required to create <optgroup>s in an ASP.NET DropdownList. You can see the output control populated with ListItems which are properly encapsulated within optiongroups below.

The source code for this approach can be downloaded from here.

Output:




HTH,

Commonly used JQuery methods and snippets

It’s been a long time since I have written anything on my blog. I seriously feel that it is turning into an “update-only-when-I-have-time” kind of thing. I don’t like it, but can’t do anything. That’s the way life goes. Anyways, there is something I have to say about JQuery. I am very much impressed with it and the way it is making everybody’s life easier. It is like the social networking fever in the software development industry where everybody seems to be talking about JQuery, its plug-ins and trying to find new ways to use it in one way or the other. It is a good thing. I also use it whenever I see even a little room to insert JavaScript in web applications. I can’t recall when was the last time I used  document.getElementById():). JQuery is taking over the world. All we need to do is to keep up with its pace if we want to get ahead in web development business.

The thing which bothers me more than anything else whenever I use JQuery is the fact that it’s all scattered. A small number of commonly used JQuery methods are being used everywhere repeatedly without change. This is definitely not a problem with JQuery, but with me as I am a long time fan of putting all the JavaScript dirty stuff in one file. I guess the same can’t be achieved with JQuery for its methods are tightly coupled with the HTML elements on the page.

One might think what I am trying to achieve here. My intention is to have all the JQuery methods in one place so that I can come back to them whenever I need them. I know the JQuery documentation is there exactly for this purpose, but I guess that documentation is not control-driven rather functionality driven. For example if I am using a Dropdown control on my page and using JQuery want to find out its selected value, I have to undergo the same struggle I went the last time in order to figure out all the possible methods I can use to accomplish the task. How about creating a control driven JQuery wrapper that will wrap the functionality of JQuery library core methods? err…that was just of the top of my head.

May be my thinking is not legitimate and it is just a matter of spending more time around JQuery and I will start memorizing every bit of it. May be. Anyways, for the time being, I have decided to help myself by compiling a small list of JQuery methods I HAVE USED SO FAR in different scenarios in order to commit it to my memory. This list will be updated with more methods in future as I use them.

  • Checkbox list has at least one item CHECKED (.length())
    example:
    if ($("div.container input:checked").length == 0)

  • CHECK/UNCHECK a Checkbox (.attr(name,value) / .removeAttr(name))
    example:
    if ($("input:checkbox").attr("checked") == true)
    $("input:checkbox").removeAttr("checked");
    else
    $("input:checkbox").attr("checked", "checked");

  • Dropdown list has a SELECTED item (.val())
    example:
    if ($("div.container select.dropdownlist").val() != -1)

  • VALUE of the Selected Checkbox (.attr())
    example:
    $("div.container input:checked").attr("value"); 

  • TEXT between <SPAN> and </SPAN> (html())
    example:
    $("div.container input:checked").find("span").html();

  • Setting the VALUE of a Textbox or a Hidden field (.val(value))
    example:
    $("div.container").siblings("#<%=hSelectedItem.ClientId%>").val(selectedVal);

  • Getting a STYLE property from first matched element (.css())
    example:
    if ($(this).siblings('.container).css("display") == 'none')) 

  • Animating the element OPACITY  (.fadeIn() / .fadeOut())
    examples:
    $(this).siblings('.itemlist').fadeIn(200);     
    $(this).siblings('.itemlist').fadeOut(200);

  • Switching between EXPAND and COLLAPSE images (.attr(name,value))
    example:
    $(this).children("img").attr("src", '<%=ImagePath%>Collapse.png');  
    $(this).children("img").attr("src", '<%=ImagePath%>Expand.png');

  • Changing the CSS CLASS NAME (.addClass(name))
    example:
    $(this).addClass("selected");

  • Creating the <OPTGROUP>s in an ASP.NET Dropdown list (.wrapAll())
    I did I blog post here about it a while ago where I have shown how <OPTGROUP>s can be created in an ASP.NET Dropdown list using just two lines of JQuery code.
    example:
    $("select.dropdownlist option[@type='1']").wrapAll('<optgroup label="Level1">'); 
    $("select.dropdownlist option[@type='2']").wrapAll('<optgroup label="Level2">');

  • Getting a COMMA SEPERATED LIST of VALUES of selected Checkboxes (.SerializeArray())
    The below small function makes use of JQuery .SerializeArray() method which returns form elements as an array of name/value pair. Each element’s value will then be pushed into another array and returned as a comma separated string.
    function GetSelectedApplicants()     
    {
    var fields = $("tr td input:checkbox:checked").serializeArray();
    $.each(fields, function(i, field)
    {
    selectedApplicants.push(field.value);
    });
    return selectedApplicants.join(',');
    }

  • Creating a DYNAMIC TOOLTIP containing the data from ASP.NET web server. (.ajax())
    I wanted to create a fancy dynamic tooltip like the one on LinkedIN® and Google Dictionary Lookup in Chrome. I ended up using JQuery .ajax() method which is calling ASP.NET server-side function asynchronously and after retrieving the data populating the tooltip container with HTML elements around the data.
    function GetItemList(item, appID) 
    {
    $.ajax({
    type: "POST",
    url: "ListApplicants.aspx/GetFolderList",
    data: "{id: " + appID + "}",
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function(msg)
    {
    //hiding the loading bar once the resluts has been retrived.
    item.parent().children(".loadingbar").css("display", "none");
    item.parent().append(
    '<div class="toolTipWrapper">'
            + '<div class="closex" onclick="closex();">[x]</div>'
                    + msg.d
            + '<div class="arrowContainer">'
            + '<div class="arrowInner"></div>'
        + '<div class="arrowOuter"></div>'
    + '</div>'
    + '</div>'
    )
    }
    });
    }

  • Clearing the TEXT field on focus (.focus())
    Sometimes we need to display a default text in the textbox like “Click here to search” or “email address” to inform the user what needs to go in the textbox. The below snippet makes it easier for us to clear the text as soon as the user clicks on the textbox to type something.
    $("input.text").focus( function() {     
            if ( $(this).val() == '(email address)' || $(this).val() == 'Site Search...' )
            $(this).val('');                
    } );

  • Selecting an element which does NOT have a particular stylesheet. (:not())
    example:
    $("div.container div p:not(.quote)").css('display', 'none');

  • Appending the content of an element to the end of another element (.append())
    example:
    $("td.column").append($("div.row").contents());

Honestly, I have no intension to write another JQuery documentation, but at times it makes a lot of sense to have everything we have used so far in one place, specially if it is just one group of things being repeated again and again. The ultimate goal is to scribble down the way I have used JQuery methods with web/HTML controls.


HTH,