Solved

Mutually exclusive checkbox in a gridview

Posted on 2016-10-24
18
61 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 54

Expert Comment

by:Julian Hansen
ID: 41858148
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
ID: 41858182
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 54

Expert Comment

by:Julian Hansen
ID: 41858279
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
PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

 

Author Comment

by:AnneSKS
ID: 41858472
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 54

Expert Comment

by:Julian Hansen
ID: 41858616
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 54

Expert Comment

by:Julian Hansen
ID: 41859435
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
ID: 41859451
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 54

Expert Comment

by:Julian Hansen
ID: 41859489
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 54

Expert Comment

by:Julian Hansen
ID: 41859541
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
 

Author Comment

by:AnneSKS
ID: 41859555
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
ID: 41861759
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 54

Expert Comment

by:Julian Hansen
ID: 41861801
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
ID: 41863348
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
ID: 41863640
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 54

Accepted Solution

by:
Julian Hansen earned 500 total points
ID: 41864155
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
ID: 41864642
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 54

Expert Comment

by:Julian Hansen
ID: 41864919
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 54

Expert Comment

by:Julian Hansen
ID: 41865081
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

Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
This article demonstrates how to create a simple responsive confirmation dialog with Ok and Cancel buttons using HTML, CSS, jQuery and Promises
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…

770 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