Monday, February 18, 2008

GridView CheckBox Adding Javascript Event

My colleague asked me whether it is possible to add a JavaScript event to CheckBox row in GridView.

The scenario is :

  1. There are 5 checkboxes in each of the row in GridView.
  2. Total checks is the number of checkboxes which are being checked in the row
  3. Frequency is the limit number of total checkboxes which will be allowed to be checked in the row
This should be able to be done in the backend / postback, but unless you're using ajax to do this, it would be bad if page always postbacks everytime the user selects a checkbox ;)

Steps :
  1. Add OnRowDataBound="gvTest_OnRowDataBound" event to the gridview
  2. Add onclick attributes on the checkboxes in the event
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
    CheckBox chkW1 = e.Row.FindControl("chkW1") as CheckBox;
    CheckBox chkW2 = e.Row.FindControl("chkW2") as CheckBox;
    CheckBox chkW3 = e.Row.FindControl("chkW3") as CheckBox;
    CheckBox chkW4 = e.Row.FindControl("chkW4") as CheckBox;
    CheckBox chkW5 = e.Row.FindControl("chkW5") as CheckBox;

    Label lblTotalChecks = e.Row.FindControl("lblTotalChecks") as Label;
    Label lblFrequency = e.Row.FindControl("lblFrequency") as Label;

    string validationScript = string.Format("return ValidateCheckAtRow('{0}', '{1}', '{2}', '{3}', '{4}', '{5}', '{6}');"
    , chkW1.ClientID
    , chkW2.ClientID
    , chkW3.ClientID
    , chkW4.ClientID
    , chkW5.ClientID
    , lblTotalChecks.ClientID
    , lblFrequency.ClientID);

    chkW1.Attributes.Add("onclick", validationScript);
    chkW2.Attributes.Add("onclick", validationScript);
    chkW3.Attributes.Add("onclick", validationScript);
    chkW4.Attributes.Add("onclick", validationScript);
    chkW5.Attributes.Add("onclick", validationScript);
    }

  3. Add javascript function ValidateCheckAtRow
    function ValidateCheckAtRow(w1, w2, w3, w4, w5, totalchecks, frequency)
    {
    try
    {
    var chkW1 = document.getElementById(w1).checked;
    var chkW2 = document.getElementById(w2).checked;
    var chkW3 = document.getElementById(w3).checked;
    var chkW4 = document.getElementById(w4).checked;
    var chkW5 = document.getElementById(w5).checked;
    var lblFrequency = document.getElementById(frequency);
    var lblTotalChecks = document.getElementById(totalchecks);
    var limit = ReadSpanElementText(lblFrequency);
    var total = 0;

    if (chkW1)
    {
    total += 1;
    }
    if (chkW2)
    {
    total += 1;
    }
    if (chkW3)
    {
    total += 1;
    }
    if (chkW4)
    {
    total += 1;
    }
    if (chkW5)
    {
    total += 1;
    }

    if (total > limit)
    {
    alert('You have exceed the limit for the row!');
    return false;
    }
    else
    {
    WriteSpanElementText(lblTotalChecks, total);
    return true;
    }
    }
    catch(e)
    {
    alert(e);
    return false;
    }
    }

    function ReadSpanElementText(sp)
    {
    if (window.ActiveXObject)
    {
    return sp.innerText;
    }
    // code for Mozilla, Firefox, Opera, etc.
    else if (document.implementation && document.implementation.createDocument)
    {
    return sp.firstChild.nodeValue;
    }
    }

    function WriteSpanElementText(sp, val)
    {
    // code for IE
    if (window.ActiveXObject)
    {
    sp.innerText = val;
    }
    // code for Mozilla, Firefox, Opera, etc.
    else if (document.implementation && document.implementation.createDocument)
    {
    sp.firstChild.nodeValue = val;
    }
    }


Notes :
  • The ClientID is only available on the OnRowDataBound event, if you try to use this in the OnRowCreated event, it will render the raw "chkW1" id instead of something like "gvTest_ctl02_chkW1"
  • When the checkboxes are being rendered, you may notice that it will actually render checkbox input inside of a span element, the javascript event will also be rendered in the span element, instead of the checkbox input control. That's why we use onclick event to get it works (onchange will work on FireFox but not on IE) and if validate function return false, the checkbox will automatically unchecked as well ;)
Of course there are other workarounds such as using javascript to parse the control id, but i find this way is more straight forward by using the id directly ;)

Just another thoughts of mine ;)

** Updates: The old location is not available anymore, I have uploaded a newer one here

3 comments:

Anonymous said...

Hi Arifin
the sample code link isn't working, would appreciate if you can fix it.
thanks
Anonymous

Bembeng Arifin said...

Hi there,
I have uploaded a new one for you.

Anonymous said...

how to give separte id for each checkboxes in a data gridview?

Post a Comment