Multi select DropDownList in ASP.NET

I needed a dropdown list that allows multi select, a sort of checkbox list paired with a dropdown. For example is very useful when working with months. MS Reporting Services has one.

After googling for a while, I couldn’t find one to satisfy me and I started to play with a dropdown. A click on dropdown and a list of checkboxes appears, another click and the list dissappears. Problem was that the dropdown wanted to show it’s “Select month” option.

Long story short, I paired a TextBox, styled with css to have a “select arrow”, with a CheckBoxList and some jQuery:

Multiselect DropDownList

And here is the code: MonthsControl-src.7z

Advertisements

Cannot pass arguments to OnClientClick javascript

I want to give more information to the confirm dialog when the user deletes a record.
I’m using an asp:LinkButton that can execute some javascript when the user clicks it, in the “OnClientClick” property.

<ItemTemplate>
     <asp:LinkButton ID="lnkClose" runat="server" CausesValidation="False"
         data-number='<%# Eval("Number") %>' CommandArgument='<%# Eval("Id") %>'
         CommandName="close" CssClass="selected_item close-project">Close
    </asp:LinkButton>
 </ItemTemplate>

Unfortunately, I cannot pass the project number as an argument to the javascript function in OnClientClick.

Luckily, there is jQuery:

$('#ProjectsList a.close-project').live("click", function()
 {
     var $parentRow = $(this).parent().parent();
     $parentRow.toggleClass("current");

     var projectNumber = $(this).attr("data-number");
     var answer = confirm("Close project " + projectNumber + "?");
     if (!answer)
     {
          $parentRow.toggleClass("current");
     }
     return answer;
 });

Update: There is a way to pass arguments:

http://forums.asp.net/t/980311.aspx/1?Eval+in+an+OnCLientClick

jQuery Validation and select tags

Just a note to myself, when using jQuery Validation for a select, make sure the first value, "Please select an option" has an empty value.

Like this:

<select id="regions" class="required" name="regions">
    <option value="">Please select an option</option>
    <option value="1">Region 1</option>
    <option value="2">Region 2</option>
</select>

Here’s the original text:

http://docs.jquery.com/Plugins/Validation/Methods/required

Validate a form on a click (pun intended)

I have a grid with users, where for each user several reports can be generated.

The reports must have a start and end date and because some technical constraints and because I wanted to let users re-use an url, I decided to send the values by query string.

Then, I had to add some validation, so that the user would be forced to select the report dates.

Then, the problem, how to prevent the click on the link if the form was not valid?

Here’s the solution:

 

<div id="start-date-area">
    <p>Select the start date:</p>
    <input id="cal-from-date" name="from" type="text" class="required for-report clickable" readonly="readonly" />
    <p></p>
</div>
<div id="end-date-area">
    <p>Select the end date:</p>
    <input id="cal-to-date" name="to" type="text" class="required for-report clickable" readonly="readonly" />
    <p></p>
</div>

 

$("a.submit").live("click", function(ev)
{
    ev.preventDefault();
    var $self = $(this);

    $("#aspnetForm").validate();
    if ($("#aspnetForm").valid())
    {
        // generate a querystring fragment from the fields I need to send to the server
        var qs = $(".for-report").serialize();

        //console.log("qs: " + qs);
        document.location = $self.attr("href") + "&" + qs;
    }
});

I have used $("a.submit").live("click", function(ev) instead of

$("a.submit").click(function(ev) because the rows are added in the grid using ajax and click works only on current elements and not on possible future elements.

jQuery.serializeArray() works also outside a form

 

Quote from jQuery docs: "Note that serializeArray() only works on form elements, using this method on another element will not work."

(http://docs.jquery.com/Ajax/serializeArray)

 

However, this is wrong, at least in 1.4.2 because I’m using the function to send some params to a controller this way:

<input type="hidden" id="LicenseId" name="LicenseId" value="" class="markerDTO" />
<input type="hidden" id="marker_Color" name="marker.Color" value="" class="markerDTO" />
<input type="hidden" id="marker_Id" name="marker.Id" value="" class="markerDTO" />

The 3 fields are not included in any <form></form>

var oo = $(‘.markerDTO‘).serializeArray();

jQuery.ajax({
            url: ‘-my-url-‘,
            dataType: ‘json’,
            data: jQuery.param(oo),
            complete: function()
            {
                var licenseId = $("#LicenseId").val();
                var color = $("#marker_Color").val();

                $(‘div.marker-color[license-id=’ + licenseId + ‘]’).css(‘background-color’, color );

                // unblock when remote call returns
                jQuery.unblockUI();
            }
        });

 

Also it works with just one input:

var oo = $(‘#LicenseId’).serializeArray();

Read-only fields are not stored between roundtrips

We’ve recently upgraded a .NET 1.1 project to 3.5 to benefit from all its goodies. Almost everything went well… with a couple of exceptions.

For a while I’ve been struggling with a stupid bug: read-only fields are not saved during a postback (even with EnableViewState=true).

In this project there are some forms, with fields (asp.net controls) generated dynamically, which means their id’s are not known at design time and on top of that, some are read only (the calendar).

So at first, I did something like this in Page_Load:

string instalationReadyFieldName = "Defaulttemplate1:Content:dtbField1827";
TextBox txtInstalationReady = Page.FindControl( instalationReadyFieldName )
 							as TextBox;
if ( txtInstalationReady != null ) txtInstalationReady.Text =
					Request[instalationReadyFieldName];

But on the test server, surprise, the id’s were different and the fields were not sent to server anymore…

After several hours of searching for an elegant solution, I had an “Ahaa!”: I will use jQuery:

So I removed the readonly attribute from the controls and added some little javascript:

// when pressing a key, don't keep the value.
$(".q_inp_date").live("keypress", function(event)
{
    return false;
});

where ‘q_inp_date’ is the class added to the date, former read-only controls.