Nathan
Nathan

Reputation: 219

jQuery to make dynamically created radiobutton groups mutually exclusive

I have some C# (asp.net mvc 3) code that is generating radio buttons on the page and assigning them to groups dynamically. I have some jQuery that will make "all" radio buttons on the page mutually exclusive but that isn't exactly what the requirement is supposed to do.

Each group needs to be mutually exclusive and the code I am using now makes every radio button the page mutually exclusive and that will not work.

How can I make each group mutually exclusive? This has to be dynamic as the group name is dynamically generated at run time.

Rendered Html:

<!DOCTYPE html>

<!-- paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ -->
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="en"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="en"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="en"> <![endif]-->
<!--[if gt IE 8]><!-->
    <html class="no-js" lang="en">
<!--<![endif]-->
<meta charset="utf-8" />
<!-- Set the viewport width to device width for mobile -->
<meta name="viewport" content = "initial-scale=1,user-scalable=no,maximum-scale=1">

<head>
    <title>Approvals Edit</title>


        <link href="/camms/Content/themes/camms/jquery-ui-1.8.13.custom.css?build=1.0.4778.19080" rel="stylesheet" type="text/css" />

        <link href="/camms/Content/themes/camms/tinyeditor.css?build=1.0.4778.19080" rel="stylesheet" type="text/css" />

    <link href="/camms/Content/themes/zurb/globals.css" rel="stylesheet" type="text/css" />
    <link href="/camms/Content/themes/zurb/forms.css" rel="stylesheet" type="text/css" />
    <link href="/camms/Content/themes/zurb/grid.css" rel="stylesheet" type="text/css" />
    <link href="/camms/Content/themes/zurb/mobile.css" rel="stylesheet" type="text/css" />
    <link href="/camms/Content/themes/zurb/typography.css" rel="stylesheet" type="text/css" />
    <link href="/camms/Content/themes/zurb/app.css" rel="stylesheet" type="text/css" />


        <script src="/camms/Scripts/jquery-1.6.2.min.js?build=1.0.4778.19080" type="text/javascript"></script>

        <script src="/camms/Scripts/jquery-ui-1.8.16.min.js?build=1.0.4778.19080" type="text/javascript"></script>

        <script src="/camms/Scripts/jquery.unobtrusive-ajax.min.js?build=1.0.4778.19080" type="text/javascript"></script>

        <script src="/camms/Scripts/jquery.blockUI.js?build=1.0.4778.19080" type="text/javascript"></script>

        <script src="/camms/Scripts/jquery.scrollTo-1.4.2-min.js?build=1.0.4778.19080" type="text/javascript"></script>

        <script src="/camms/Scripts/jquery.maskedinput-1.3.js?build=1.0.4778.19080" type="text/javascript"></script>

        <script src="/camms/Scripts/tinyeditor_packed.js?build=1.0.4778.19080" type="text/javascript"></script>

        <script src="/camms/Scripts/PrintArea.js?build=1.0.4778.19080" type="text/javascript"></script>

        <script src="/camms/Scripts/jquery.base64.min.js?build=1.0.4778.19080" type="text/javascript"></script>

        <script src="/camms/Scripts/jquery.pagination.js?build=1.0.4778.19080" type="text/javascript"></script>

        <script src="/camms/Scripts/jquery.sorting.js?build=1.0.4778.19080" type="text/javascript"></script>

        <script src="/camms/Scripts/jquery.filtering.js?build=1.0.4778.19080" type="text/javascript"></script>

        <script src="/camms/Scripts/jquery.validate.js?build=1.0.4778.19080" type="text/javascript"></script>

        <script src="/camms/Scripts/CammsTemplate.js?build=1.0.4778.19080" type="text/javascript"></script>


        <script src="/camms/Scripts/jquery.stretcher.js?build=1.0.4778.19080" type="text/javascript"></script>

        <script src="/camms/Scripts/jquery.mobile-menu.js?build=1.0.4778.19080" type="text/javascript"></script>


    <link href="/camms/Content/themes/zurb/ui.css" rel="stylesheet" type="text/css" />
</head>
<body>


    <div style="position:absolute; botton:0; left:0; background-color:black; color:white">
        Development
    </div>   

        <script type="text/javascript">
        $(function () {
            $(':input:enabled:visible:first').focus();
        });

        //rootPath is used to construct URLs in attached javascript files
        rootPath = "/camms/";
    </script>


    <script src="/camms/Scripts/SessionMonitor.js?build=1.0.4778.19080" type="text/javascript"></script>


<script type="text/javascript">
    $(function() {
        var rootPath = '/camms/';
        var sessionMonitor = new SessionMonitor({
            extendSessionButton:    $('#keepWorkingBtn'),
            extendSessionUrl:       rootPath + "JSON/KeepSessionAlive",
            extendSessionMessage:   $('#extendSession'),
            sessionExpiredOkButton: $('#sessionExpiredBtn'),
            expiredSessionMessage:  $('#sessionTimedOut'),
            expiredSessionUrl:      rootPath,
            sessionTimeout :        1800
        });
    });
</script>

<div id="sessionTimedOut" style="display: none; padding:10px;">
    <p>Your session has expired</p>
    <input type="button" id="sessionExpiredBtn" class="small blue radius button" value="Ok"/>
</div>

<div id="extendSession" style="display: none; padding:10px;">
    <p>Your session will expire in <span id="sessionTimeRemaining"></span> seconds</p>
    <input type="button" id="keepWorkingBtn" class="small blue radius button" value="Keep Working"/>
</div>    

    <div class="container">
        <div id="header" class="row">
            <div id="mobile-logo" class="show-on-phones clearfix" >
                <h2>
                    <a href="/camms/">CAMMS</a>
                </h2>
            </div>

            <a href="/camms/" class="hide-on-phones">    <img src="/camms/Content/themes/camms/Images/logo.png" class="logo" alt="" />
</a>
            <div id="user-info-panel">

                <span class="hide-on-phones">
                    Wednesday, January 30, 2013<br />
                </span>

                Baker, Nathan |

                <!-- Show the current office -->
Computer Services,  Central<br />

                <!-- show the change office link -->
            </div>
        </div>


        <label id="mobile-category-name" class="show-on-phones">
            Category: Certifications
        </label>
        <div id="menuBar" class="row">
            <div id="breadcrumb" class="hide-on-phones">
                Category: Certifications
            </div>




<ul class="hide-on-phones">
        <li class='item  '>
                     <span class="disabled">Enrollment</span>

        </li>
        <li class='item selected radius '>
                     <span class="disabled">Approvals</span>

        </li>
        <li class='item  '>
                     <span class="disabled">Maintenance</span>

        </li>
        <li class='item  '>
                     <span class="disabled">Scheduling</span>

        </li>
</ul>

<label class="mobile-nav-level1 show-on-phones">
    Process:  &nbsp;
</label>
<select class="show-on-phones mobile-nav" style="margin-top:8px;">
            <option  value="/camms/Certifications/Scheduling" >
                Scheduling
            </option>
            <option  value="/camms/Certifications/Maintenance" >
                Maintenance
            </option>
            <option selected value="/camms/Certifications/Approvals" >
                Approvals
            </option>
            <option  value="/camms/Certifications/Enrollment" >
                Enrollment
            </option>
</select>

           </div>
        <div id="moreMenu">

<div class="moreMenuContainer radius" >
    <ul>
    </ul>
</div>
<span style="clear:right"></span>        </div>

        <div id="page-content" class="row radius-bottom">
            <div id="leftColumn" class="five columns">


<div style="overflow:hidden" class="hide-on-phones">
    <ul>
    </ul>
</div> 

<label class="mobile-nav-level2 show-on-phones">
    Sub-Process:  &nbsp;
</label>

<select class="show-on-phones mobile-nav " >
</select>
               </div>

            <div id="rightColumn" class="fifteen columns">
                <div id="title-bar" class="row">
                    <div id="titleBarOptions"></div>
                    <h2>Approvals Edit</h2>


                    <hr/>
                </div>

                <div id="scrollable-area" >


<form action="/camms/CertificationApproval/Edit/Certifications/Approvals/10556" method="post">    <span>

        <div class="row line editcolumn">
                <div class="three columns ">

                        <label for="PersonName" class="hide-on-phones" style="white-space: nowrap">Attendee</label>
                        <span class="clearfix hide-on-phones"></span>
                        <label for="PersonName" class="show-on-phones">Attendee &nbsp; </label>
                        <span class="clearfix show-on-phones"></span>                        


<input disabled="disabled" id="PersonName" name="PersonName" type="text" value="Brandhuber, Scott J." />
<input id="PersonName" name="PersonName" type="hidden" value="Brandhuber, Scott J." />


                </div>
                <div class="four columns ">

                        <label for="Certification" class="hide-on-phones" style="white-space: nowrap">Certification</label>
                        <span class="clearfix hide-on-phones"></span>
                        <label for="Certification" class="show-on-phones">Certification &nbsp; </label>
                        <span class="clearfix show-on-phones"></span>                        


<input disabled="disabled" id="Certification" name="Certification" type="text" value="ALDOT Concrete Technician" />
<input id="Certification" name="Certification" type="hidden" value="ALDOT Concrete Technician" />


                </div>
                <div class="one columns ">

                        <label for="Score" class="hide-on-phones" style="white-space: nowrap">Score</label>
                        <span class="clearfix hide-on-phones"></span>
                        <label for="Score" class="show-on-phones">Score &nbsp; </label>
                        <span class="clearfix show-on-phones"></span>                        


<input data-val="true" data-val-number="The field Score must be a number." data-val-required="The Score field is required." disabled="disabled" id="Score" name="Score" type="text" value="85" />
<input id="Score" name="Score" type="hidden" value="85" />


                </div>
                <div class="two columns ">

                        <label for="ExamProficiency" class="hide-on-phones" style="white-space: nowrap">Proficiency</label>
                        <span class="clearfix hide-on-phones"></span>
                        <label for="ExamProficiency" class="show-on-phones">Proficiency &nbsp; </label>
                        <span class="clearfix show-on-phones"></span>                        


<input disabled="disabled" id="ExamProficiency" name="ExamProficiency" type="text" value="" />
<input id="ExamProficiency" name="ExamProficiency" type="hidden" value="" />


                </div>
                <div class="one columns ">

                        <label for="Approve" class="hide-on-phones" style="white-space: nowrap">Approve</label>
                        <span class="clearfix hide-on-phones"></span>
                        <label for="Approve" class="show-on-phones">Approve &nbsp; </label>
                        <span class="clearfix show-on-phones"></span>                        

                    <input GroupName="group_64" falsevalue="N" id="Approve" name="Approve" truevalue="Y" type="radio" value="False" />
                </div>
                <div class="one columns ">

                        <label for="Reject" class="hide-on-phones" style="white-space: nowrap">Reject</label>
                        <span class="clearfix hide-on-phones"></span>
                        <label for="Reject" class="show-on-phones">Reject &nbsp; </label>
                        <span class="clearfix show-on-phones"></span>                        

                    <input GroupName="group_64" falsevalue="Y" id="Reject" name="Reject" truevalue="N" type="radio" value="False" />
                </div>
       </div>
<input data-val="true" data-val-number="The field Person Certification Id must be a number." data-val-required="The Person Certification Id field is required." id="PersonCertificationId" name="PersonCertificationId" type="hidden" value="1478" /><input data-val="true" data-val-number="The field Ref Wtf Members Id must be a number." data-val-required="The Ref Wtf Members Id field is required." id="RefWtfMembersId" name="RefWtfMembersId" type="hidden" value="10006" /><input data-val="true" data-val-number="The field Worker Id must be a number." data-val-required="The Worker Id field is required." id="WorkerId" name="WorkerId" type="hidden" value="10556" /><input data-val="true" data-val-number="The field Wtf Approval Id must be a number." data-val-required="The Wtf Approval Id field is required." id="WtfApprovalId" name="WtfApprovalId" type="hidden" value="0" /><input id="MembersId" name="MembersId" type="hidden" value="10011" /><input id="PreviousUrl" name="PreviousUrl" type="hidden" value="" /><input data-val="true" data-val-number="The field Last Modified By Id must be a number." id="LastModifiedById" name="LastModifiedById" type="hidden" value="" />           
        <div class="row line editcolumn">
                <div class="three columns ">

                        <label for="PersonName" class="hide-on-phones" style="white-space: nowrap">Attendee</label>
                        <span class="clearfix hide-on-phones"></span>
                        <label for="PersonName" class="show-on-phones">Attendee &nbsp; </label>
                        <span class="clearfix show-on-phones"></span>                        


<input disabled="disabled" id="PersonName" name="PersonName" type="text" value="Duck, Daffy " />
<input id="PersonName" name="PersonName" type="hidden" value="Duck, Daffy " />


                </div>
                <div class="four columns ">

                        <label for="Certification" class="hide-on-phones" style="white-space: nowrap">Certification</label>
                        <span class="clearfix hide-on-phones"></span>
                        <label for="Certification" class="show-on-phones">Certification &nbsp; </label>
                        <span class="clearfix show-on-phones"></span>                        


<input disabled="disabled" id="Certification" name="Certification" type="text" value="ALDOT Concrete Technician" />
<input id="Certification" name="Certification" type="hidden" value="ALDOT Concrete Technician" />


                </div>
                <div class="one columns ">

                        <label for="Score" class="hide-on-phones" style="white-space: nowrap">Score</label>
                        <span class="clearfix hide-on-phones"></span>
                        <label for="Score" class="show-on-phones">Score &nbsp; </label>
                        <span class="clearfix show-on-phones"></span>                        


<input disabled="disabled" id="Score" name="Score" type="text" value="70" />
<input id="Score" name="Score" type="hidden" value="70" />


                </div>
                <div class="two columns ">

                        <label for="ExamProficiency" class="hide-on-phones" style="white-space: nowrap">Proficiency</label>
                        <span class="clearfix hide-on-phones"></span>
                        <label for="ExamProficiency" class="show-on-phones">Proficiency &nbsp; </label>
                        <span class="clearfix show-on-phones"></span>                        


<input disabled="disabled" id="ExamProficiency" name="ExamProficiency" type="text" value="PASS" />
<input id="ExamProficiency" name="ExamProficiency" type="hidden" value="PASS" />


                </div>
                <div class="one columns ">

                        <label for="Approve" class="hide-on-phones" style="white-space: nowrap">Approve</label>
                        <span class="clearfix hide-on-phones"></span>
                        <label for="Approve" class="show-on-phones">Approve &nbsp; </label>
                        <span class="clearfix show-on-phones"></span>                        

                    <input GroupName="group_67" falsevalue="N" id="Approve" name="Approve" truevalue="Y" type="radio" value="False" />
                </div>
                <div class="one columns ">

                        <label for="Reject" class="hide-on-phones" style="white-space: nowrap">Reject</label>
                        <span class="clearfix hide-on-phones"></span>
                        <label for="Reject" class="show-on-phones">Reject &nbsp; </label>
                        <span class="clearfix show-on-phones"></span>                        

                    <input GroupName="group_67" falsevalue="Y" id="Reject" name="Reject" truevalue="N" type="radio" value="False" />
                </div>
       </div>
<input id="PersonCertificationId" name="PersonCertificationId" type="hidden" value="10089" /><input id="RefWtfMembersId" name="RefWtfMembersId" type="hidden" value="10006" /><input id="WorkerId" name="WorkerId" type="hidden" value="10556" /><input id="WtfApprovalId" name="WtfApprovalId" type="hidden" value="0" /><input id="MembersId" name="MembersId" type="hidden" value="10011" /><input id="PreviousUrl" name="PreviousUrl" type="hidden" value="" /><input id="LastModifiedById" name="LastModifiedById" type="hidden" value="" />
    </span>
    <div class="DetailLine NewRow Required" id="RequiredFieldLegend">
        *Indicates a required field
    </div>
    <div class="row">
        <div class="sixteen columns">
                <input name="command" type="submit" value="Save" class="small nice blue radius button"  />
                <input name="command" type="submit" value="Cancel" class="small nice white radius button"  />
        </div>
    </div>
</form>

<script type="text/javascript">
    if ($('.required').not('#RequiredFieldLegend').length == 0) {
        $('#RequiredFieldLegend').hide();
    }
</script>


                </div>
            </div>
        </div>
        <div id="footerContainer" class="row">
            <div >
                <div id="footerLinksContainer" class="radius-top">
                    <ul>
                        <li>
                                <img src="/camms/Content/themes/camms/Images/icons/ico_book.png" alt="" class="icon" />

                                    <span class="disabled">Construction Manual</span>

                        </li>
                        <li>
                                <img src="/camms/Content/themes/camms/Images/icons/ico_manual.png" alt="icon" class="icon" />

                                    <span class="disabled">Spec Book</span>

                        </li>
                        <li>
                                <img src="/camms/Content/themes/camms/Images/icons/ico_test.png" alt="icon" class="icon" />

                                    <span class="disabled">Testing Manual</span>

                        </li>
                        <li>
                                <img src="/camms/Content/themes/camms/Images/icons/ico_search.png" alt="icon" class="icon" />




                            <a href="/camms/CertificationApproval/Search/Certifications/Approvals/">Search</a>


                        </li>
                        <li>
                                <img src="/camms/Content/themes/camms/Images/icons/ico_helpBook.png" alt="icon" class="icon" />

                                    <span class="disabled">Help</span>

                        </li>
                        <li>
                                <img src="/camms/Content/themes/camms/Images/icons/ico_help.png" alt="icon" class="icon" />

                                    <span class="disabled">Help Desk</span>

                        </li>
                    </ul>
                </div>
            </div>
        </div>
    </div>










</body>

</html>

This is the Edit ViewModel:

    using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Web.UI.WebControls;
using Camms.ValueObjects;
using CammsWeb.Code;
using CammsWeb.Code.Attributes;
using CammsWeb.Attributes;
using CammsWeb.Code.TemplateElements;

namespace CammsWeb.Models.Categories.Certifications.Approvals
{
    public class ApprovalEditViewModel : ViewModelBase
    {
        public long PersonCertificationId { get; set; }

        public long RefWtfMembersId { get; set; }

        public long WorkerId { get; set; }

        public long WtfApprovalId { get; set; }

        public string MembersId { get; set; }

        // this will be Y or N for approve/reject
        public string Vote { get; set; }

        [Layout(3), DisplayName("Attendee"), Disable()]
        public string PersonName { get; set; }

        [Layout(4), DisplayName("Certification"), Disable()]
        public string Certification { get; set; }

        [Layout(1), DisplayName("Score"), Disable()]
        public double Score { get; set; }

        [Layout(2), DisplayName("Proficiency"), Disable()]
        public string ExamProficiency { get; set; }

        [Layout(1), DisplayName("Approve"), RadioButton(FalseValue = "N", TrueValue = "Y")]
        public string Approve { get; set; }

        [Layout(1), DisplayName("Reject"), RadioButton(FalseValue = "Y", TrueValue = "N")]
        public string Reject { get; set; }

    }
}

Upvotes: 0

Views: 1392

Answers (2)

Eli Gassert
Eli Gassert

Reputation: 9763

Given the groupname attribute, you can do this:

$(':radio[groupname]').change(function()
{
  var groupname = $(this).attr('groupname');
  var filter = ':radio[groupname="' + groupname + '"]';


  $(filter).attr('checked', false); // find all elements with the same groupname, uncheck them

  $(this).attr('checked', true); // reset to checked since we probably just unchecked it with the line above!
});

http://jsfiddle.net/7nAsJ/

Now, for this to work, names MUST be unique. In the JSFiddle above, you'll see I renamed Approve and Reject to Approve2 and Reject2 in the sample HTML code. So if you have two radio buttons with the name Approve then they're auto-grouped by HTML DOM standards and they will be automatically mutually exclusive. If you can't have that, then there are two other options:

  1. On load,change the name and IDs to append the group name. Then use the JS above. But if you're going to change the names anyway, then I suggest option #2...
  2. Change the name to the groupname, and then no JS will be required anyway! It's automatic.

To demonstrate, here's the code to fix the names: http://jsfiddle.net/7nAsJ/1/

$(':radio[groupname]').each(function()
{
  var groupname = $(this).attr('groupname');
  $(this).attr('name', groupname);
  $(this).attr('id', $(this).attr('id') + '_' + groupname); // set new ID to old ID_groupname for uniqueness
});

Upvotes: 1

Nope
Nope

Reputation: 22339

The way this framework works, it reads from the metadata to generate the html. The markup looks like this <input type="radio" name="Approve" id="Approve" groupname="group_1" /> <input type="radio" name="Reject" id="Reject" groupname="group_1" />

Seeing you have an attribute called groupname, according to your comment, you should be able to do something similar to this:

$("input:radio").on("click", function(){
    var $currentInput = $(this);
    var groupName = $currentInput.attr("groupname");

    $("[groupname='" + groupName + "']").not($currentInput).prop("checked", false);
})

DEMO - Manually clearing radio buttons in same group


Assuming all inputs have a groupname attribute, similar ot this:

<span>Group 1</span>
<input type="radio" groupname="group1"/>
<input type="radio" groupname="group1"/>
<input type="radio" groupname="group1"/>
<input type="radio" groupname="group1"/>
<br />
<span>Group 2</span>
<input type="radio" groupname="group2"/>
<input type="radio" groupname="group2"/>
<input type="radio" groupname="group2"/>
<input type="radio" groupname="group2"/>

Upvotes: 1

Related Questions