Solved

Mutually exclusive checkbox in a gridview

Posted on 2016-10-24
18
40 Views
Last Modified: 2016-10-29
Hi,
I have a gridview with 4 rows, and a checkbox on the first column.
When a user click on the checkbox in any one row, the checkboxes from the other rows should become uncheck.
Below is the Gridview,
The javascript code to uncheck the checkboxes from the other rows
The javascript onclick event generated on the RowDataBound event of the grdview.

The code run successfully on the RowDataBound, and populate the onclick even. However when I click on a checkbox, the other checkboxes are not unticked.

I am just starting to work with JavaScript, could you please help me with this one.

Thank you




Gridview:
<asp:Panel ID="pnlParameter" runat="server" Visible="false">
   <asp:Label ID="lblFQID" runat="server"/>
</asp:Panel>

<asp:GridView ID="GV" runat="server" AutoGenerateColumns="false" OnRowDataBound="GV_RowDataBound">
    <Columns>
        <asp:TemplateField HeaderText="Correct answer">
        <ItemTemplate>
             <asp:CheckBox ID="CheckBox1" runat="server" />
        </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField Visible="true" HeaderText="Description">
        <ItemTemplate>
            <asp:TextBox ID="txtQuestionDesc" Text='<%# Eval("QuestionDesc") %>' runat="Server" />
        </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

Open in new window


JavaScript function:
<script type="text/javascript" language="javascript">
    function uncheckOthers(id) {
        var elm = document.getElementsByTagName('input');
        for (var i = 0; i < elm.length; i++) {
            if (elm.item(i).id.substring(id.id.lastIndexOf('_')) == id.id.substring(id.id.lastIndexOf('_'))) {
                if (elm.item(i).type == "checkbox" && elm.item(i) != id)
                    elm.item(i).checked = false;
            }
        }
    }
   </script>

Open in new window


C# event:
        protected void GV_RowDataBound(object source, GridViewRowEventArgs e)
        {
            if (e.Row is GridViewRow & e.Row.RowType == DataControlRowType.DataRow)
            {
                string strScript = "uncheckOthers(" + ((CheckBox)e.Row.Cells[0].FindControl("CheckBox1")).ClientID + ");";
                ((CheckBox)e.Row.Cells[0].FindControl("CheckBox1")).Attributes.Add("onclick", strScript);
            }
        }

Open in new window

0
Comment
Question by:AnneSKS
  • 10
  • 8
18 Comments
 
LVL 51

Expert Comment

by:Julian Hansen
Comment Utility
Why not use a radio button? A radio button is exactly that - a mutually exclusive check box?

Failing that you can do this quite easily with jQuery
HTML
    <input type="checkbox" class="exclusive" data-linked="group1" value="1"/><br/>
    <input type="checkbox" class="exclusive" data-linked="group1" value="2"/><br/>
    <input type="checkbox" class="exclusive" data-linked="group1" value="3"/><br/>
    <input type="checkbox" class="exclusive" data-linked="group1" value="4"/>

Open in new window

jQuery
<script src="http://code.jquery.com/jquery.js"></script>
<script>
$(function() {
  $('.exclusive').mousedown(function() {
    var linked = $(this).data('linked');
    $(':checkbox[data-linked="' + linked + '"]').prop('checked', false);
  });
});
</script>

Open in new window

Working sample here
0
 

Author Comment

by:AnneSKS
Comment Utility
Hi Julian,
Thank you for your comment.
I'm ok with radio button, however
there is only 1 radio button/checkbox per row. And you can only select one in the gridview.
I've got the impression that your 4 radio buttons are on the same row.
0
 
LVL 51

Expert Comment

by:Julian Hansen
Comment Utility
If you look at the sample I posted (and read the Breakdown) you will see in the third group of buttons I have mixed them.

The whole purpose of the design is that you can put the checkbox anywhere on your page and link them to any other checkbox simply by
a) Adding the "exclusive" class to the checkbox
b) Adding the data-link custom attribute to the checkbox and setting it to the group name you want the checkbox to be part of
c) Including the jQuery code I posted in my post above and the sample

Here is a link to the sample again - look at the Group 3 (Mixed) group. That is made up of items from group1 and group2 - when you click the checkboxes in this group it changes the state of the checked buttons in Group 1 and Group 2
0
 

Author Comment

by:AnneSKS
Comment Utility
The problem in my post is not the grouping of checkbox and the exclusivity.
The problem is how to set up the exclusivity or the group in a the gridview, when the checkbox are in different rows, therefore the group cannot be hardcoded.

If you look at my code, in the  GV_RowDataBound event of the gridview, I am attempting to create a group. However it is not working.
0
 
LVL 51

Expert Comment

by:Julian Hansen
Comment Utility
when the checkbox are in different rows, therefore the group cannot be hardcoded.
I don't see the problem - the solution I provided allows for this?
You can have this

<table>
  <tr>
    <td><input type="checkbox" class="exclusive" data-link="group1" value="1"/></td>
  </tr>
  <tr>
    <td><input type="checkbox" class="exclusive" data-link="group1" value="2"/></td>
  </tr>
  <tr>
    <td><input type="checkbox" class="exclusive" data-link="group1" value="3"/></td>
  </tr>
  <tr>
    <td><input type="checkbox" class="exclusive" data-link="group1" value="4"/></td>
  </tr>
</table>

Open in new window

It will work - all you need to do is give the checkboxes a class of "exclusive" and for all those that are in the same group a custom attribute data-link="group1"
0
 
LVL 51

Expert Comment

by:Julian Hansen
Comment Utility
when the checkbox are in different rows, therefore the group cannot be hardcoded.
Can you explain why you think they cannot be grouped?
0
 

Author Comment

by:AnneSKS
Comment Utility
Julian,
I am talking about a gridview, not a table. They don't work the same. As I said, hard coding in html the group will not work. Believe me.
The group has to be generated in the RowDatabound event of the gridview, please check the code below. But in the work that I have done, it does not work.

In the event, I am 'grouping' the  checkbox using the following code. It should theoretically call a javascript function 'UncheckOthers' when one of the 'onclick' event of any of these check box is fired.

 string strScript = "uncheckOthers(" + ((CheckBox)e.Row.Cells[0].FindControl("CheckBox1")).ClientID + ");";
                ((CheckBox)e.Row.Cells[0].FindControl("CheckBox1")).Attributes.Add("onclick", strScript);

However, the RowDataBound event is fired and theoretically the script is added to the onclick event, when I run the form, the checkbox are not unticked when I tick one.

So I don't know, if there is a problem in either the strscript or in adding the script to the onclick event, or maybe the problem is in the javascript function. As I said previously I am not very good at JavaScript, so I could have missed something.        

Also, I am using an <asp:Checkbox/>, as I need to save the gridview result and which box has been ticked/unticked. There is a lot more in this gridview, but I have streamlined it to just show the current requirements.    

Thank you for your help.


<asp:GridView ID="GV" runat="server" AutoGenerateColumns="false" OnRowDataBound="GV_RowDataBound">
    <Columns>
        <asp:TemplateField HeaderText="Correct answer">
        <ItemTemplate>
             <asp:CheckBox ID="CheckBox1" runat="server" />
        </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField Visible="true" HeaderText="Description">
        <ItemTemplate>
            <asp:TextBox ID="txtQuestionDesc" Text='<%# Eval("QuestionDesc") %>' runat="Server" />
        </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

Open in new window


protected void GV_RowDataBound(object source, GridViewRowEventArgs e)
        {
            if (e.Row is GridViewRow & e.Row.RowType == DataControlRowType.DataRow)
            {
                string strScript = "uncheckOthers(" + ((CheckBox)e.Row.Cells[0].FindControl("CheckBox1")).ClientID + ");";
                ((CheckBox)e.Row.Cells[0].FindControl("CheckBox1")).Attributes.Add("onclick", strScript);
            }
        }

Open in new window


<script type="text/javascript" language="javascript">
    function uncheckOthers(id) {
        var elm = document.getElementsByTagName('input');
        for (var i = 0; i < elm.length; i++) {
            if (elm.item(i).id.substring(id.id.lastIndexOf('_')) == id.id.substring(id.id.lastIndexOf('_'))) {
                if (elm.item(i).type == "checkbox" && elm.item(i) != id)
                    elm.item(i).checked = false;
            }
        }
    }
   </script>

Open in new window

0
 
LVL 51

Expert Comment

by:Julian Hansen
Comment Utility
The table was to demonstrate a concept

1. Can you add a class to your checkbox items
2. Can you add a custom attribute

That is all you need. You appear to be trying to handle the unchecking in the Event handler which is unnecessary as you can handle it in the client with a few lines of JavaScript.

Remember your ASP code generates HTML - it does not matter what HTML it generates as long as you can add a class to your checkbox controls and a custom data attribute. That is all you need to do and the JavaScript code I provided will work.
0
 
LVL 51

Expert Comment

by:Julian Hansen
Comment Utility
Ok I went ahead and built an ASPX version of this. One little fact I was unaware of was that ASP wraps checkboxes inside a <span> so you need to modify the jQuery a bit to take that into account.

Here is how I defined my checkbox
        <asp:TemplateField HeaderText="Correct answer">
            <ItemTemplate>
                 <asp:CheckBox ID="CheckBox1" runat="server" CssClass="exclusive" data-linked="group1"/>
            </ItemTemplate>
        </asp:TemplateField>

Open in new window


Here is the updated jQuery code
<script>
    $(function () {
        $('span.exclusive').mousedown(function () {
            var linked = $(this).data('linked');
            $('span[data-linked="' + linked + '"] input:checkbox').prop('checked', false);
        });

    });
</script>

Open in new window

Works as expected
0
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 

Author Comment

by:AnneSKS
Comment Utility
Hi Julian,
You are fantastic. I am in meeting all morning, but will implement it early afternoon (Australian time), and let you know how I am going.

So if I understand, I have to create a user control for my checkbox and create a data-linked property and add the CSSClass . This usercontrol can go into the gridview.

Now if I only have one set of checkbox, and they are all in the same group, do I need the data-linked property, or the cssclass can be enough? Which mean in this case that I don't need to create the usercontrol.

Then in the RowDataBound event of the gridview I have to add your function to the onclick event of this usercontrol.

And then of course add the function into my page.

Thank you

Anne
0
 

Author Comment

by:AnneSKS
Comment Utility
Hi Julian,
I cannot make it work. There is too many parameters that I don't know to solve the issue.
Would you mind having a look at my code, and see if it works for you, and if not what does not work.

Theoretically it should be working, and it could be a simple mistake.

Thanks

Anne
0
 
LVL 51

Expert Comment

by:Julian Hansen
Comment Utility
I can - if you post what you have done.

Here is my code
Code behind I use to create the data source for the grid
using System;
using System.Data;

public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
        //Multi-Dimensional Array
        string[,] arrMultiD = { 
                            { "John", "21", "Berlin", "Germany" }, 
                            { "Smith", "33" ,"London", "UK"}, 
                            { "Ryder", "15" ,"Sydney", "Australia"}, 
                            { "Jake", "18", "Tokyo", "Japan"}, 
                            { "Tom","34" , "Mumbai", "India"}
                         };
        DataTable dt = new DataTable();
        dt.Columns.Add("Name", Type.GetType("System.String"));
        dt.Columns.Add("Age", Type.GetType("System.String"));
        dt.Columns.Add("City", Type.GetType("System.String"));
        dt.Columns.Add("Country", Type.GetType("System.String"));     
        for (int i = 0; i < 5; i++)
        {
            dt.Rows.Add();
            dt.Rows[dt.Rows.Count - 1]["Name"] = arrMultiD[i, 0];
            dt.Rows[dt.Rows.Count - 1]["Age"] = arrMultiD[i, 1];
            dt.Rows[dt.Rows.Count - 1]["City"] = arrMultiD[i, 2];
            dt.Rows[dt.Rows.Count - 1]["Country"] = arrMultiD[i, 3];   
        }
        GridMultiD.DataSource = dt;
        GridMultiD.DataBind();  
    }
}

Open in new window

Here is my aspx file
<%@ Page Language="C#" AutoEventWireup="true" Inherits="_Default" Codebehind="CSharp.aspx.cs" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
 
<head runat="server">
    <title>Binding Array to GridView Example</title>
    <script src="http://code.jquery.com/jquery.js"></script>
    <script>
        $(function () {
            $('span.exclusive').mousedown(function () {
                var linked = $(this).data('linked');
                $('span[data-linked="' + linked + '"] input:checkbox').prop('checked', false);
            });

        });
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    <br />
    <asp:GridView ID="GridMultiD" runat="server" 
        AutoGenerateColumns = "false" Font-Names = "Arial" 
        Font-Size = "11pt" AlternatingRowStyle-BackColor = "#C2D69B"  
        HeaderStyle-BackColor = "green" AllowPaging ="true"   
        PageSize = "10" Caption = "Multi-Dimensional Array" >
       <Columns>
        <asp:TemplateField HeaderText="Correct answer">
            <ItemTemplate>
                 <asp:CheckBox ID="CheckBox1" runat="server" CssClass="exclusive" data-linked="group1"/>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:BoundField ItemStyle-Width = "150px" DataField = "Name" HeaderText = "Name" />
        <asp:BoundField ItemStyle-Width = "150px" DataField = "Age" HeaderText = "Age" />
        <asp:BoundField ItemStyle-Width = "150px" DataField = "City" HeaderText = "City" />
        <asp:BoundField ItemStyle-Width = "150px" DataField = "Country" HeaderText = "Country" />
       </Columns> 
    </asp:GridView>    
    </div>
    </form>
</body>
</html>

Open in new window

I have a working sample here
0
 

Author Comment

by:AnneSKS
Comment Utility
Hi Julian,
I am almost there, I have managed to make it work if the checkbox and the functions are in a page. However it does not work if it is in a user control.
Any suggestions?
Thanks again for your help.

Anne
0
 

Author Comment

by:AnneSKS
Comment Utility
I found the problem, the problem is with postback in an update panel. After the postback, the checkboxes are not mutually exclusive anymore.

Any idea how to change/prevent it

Thank you

Anne
0
 
LVL 51

Accepted Solution

by:
Julian Hansen earned 500 total points
Comment Utility
That is because the checkboxes are being created dynamically

To solve this we use the .on() and bind it to a parent element

Try this. Replace the jQuery with this. Here I have replaced the mousedown() event with an .on() which is attached to body and I have specified the span.exclusive selector as being the target. So even if check boxes are added dynamically (like after a postback) the event should fire on the new elements.

 $(function () {
            $('body').on('mousedown', 'span.exclusive', function () {
                var linked = $(this).data('linked');
                $('span[data-linked="' + linked + '"] input:checkbox').prop('checked', false);
            });
        });

Open in new window

0
 

Author Closing Comment

by:AnneSKS
Comment Utility
Hi Julian,
Thank you so much for your help, it was fantastic.

I am just starting to learn JavaScript and JQuery, I am using Lynda.com to learn.
Is there any website that you would recommend, especially one with samples, or that could explain when they are best to use.

Once again thank you so much.

Anne
0
 
LVL 51

Expert Comment

by:Julian Hansen
Comment Utility
You are most welcome.

To tell the truth - I learned most of what I know hanging around EE looking at the questions people ask, trying to answer them and looking at the solutions.

There are a couple of good books out there recommended by various experts - I will try and dig up the URLS.

JavaScript is very mature the Net is littered with thousands of resources so Google could also be your friend here.
1
 
LVL 51

Expert Comment

by:Julian Hansen
Comment Utility
Here are the resources I mentioned

https://www.manning.com/books/secrets-of-the-javascript-ninja
http://shop.oreilly.com/product/9780596802806.do

There is also this site which has some good resources

http://ejohn.org/apps/learn/
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

This article will give core knowledge of JavaScript and will head in to your first JavaScript program. I am Durvesh Naik and I am here to deal with this series of JavaScript. I will teach you JavaScript in part wise , as its quite boring to read big…
This article discusses how to create an extensible mechanism for linked drop downs.
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now