Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RadioButtonList not firing SelectedIndexChanged every time

I have a RadioButtonList with "Not Applicable", "Not Available", "Leave" and "Available" options.

  1. I am throwing confirm message box on click of "Leave" in RadioButtonList from Server side as below

    protected void rdlUser_SelectedIndexChanged(object sender, EventArgs e)
    {
        radWindowManager.RadConfirm("Are you sure you want to take leave?", "confirmLeave" + this.ClientID, 300, 100, null, "");
    }
    
  2. If user clicks "Cancel", then it will automatically selects "Available" with below code.

The following is the javascript code to "Ok" or "Cancel" leave.

    function confirmLeave<%=this.ClientID%>(arg) {
        if (arg == true) {
            alert("User has selected Leave.")
        }    
        else {
            var rdlUser = docment.getElementById("<%= rdlUser.ClientID %>");
            var radioButtons = rdlUser.getElementsByTagName('input');
            radioButtons[1].checked = true;
        }
    }

If the user clicks "Leave" for the 2nd time, the SelectedIndexChanged does not fire at all.

I am flexible to move Server Side code to Client side also.

Update

The following is the relevant HTML code

<table id="ctl00_ContentPlaceHolder1_MyUser_MyMonday_rdlUser">
<tr>
    <td><span class="leave"><input id="ctl00_ContentPlaceHolder1_MyUser_MyMonday_rdlUser_0" type="radio" name="ctl00$ContentPlaceHolder1$MyUser$MyMonday$rdlUser" value="SLOT01" disabled="disabled" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;ctl00$ContentPlaceHolder1$MyUser$MyMonday$rdlUser$0\&#39;,\&#39;\&#39;)&#39;, 0)" /><label for="ctl00_ContentPlaceHolder1_MyUser_MyMonday_rdlUser_0">Not Applicable</label></span></td>
    <td><span class="leave"><input id="ctl00_ContentPlaceHolder1_MyUser_MyMonday_rdlUser_1" class="Leave" type="radio" name="ctl00$ContentPlaceHolder1$MyUser$MyMonday$rdlUser" value="SLOT02" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;ctl00$ContentPlaceHolder1$MyUser$MyMonday$rdlUser$1\&#39;,\&#39;\&#39;)&#39;, 0)" /><label for="ctl00_ContentPlaceHolder1_MyUser_MyMonday_rdlUser_1">Not Available</label></span></td>
</tr><tr>
    <td><span class="leave"><input id="ctl00_ContentPlaceHolder1_MyUser_MyMonday_rdlUser_2" class="Leave" type="radio" name="ctl00$ContentPlaceHolder1$MyUser$MyMonday$rdlUser" value="SLOT03" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;ctl00$ContentPlaceHolder1$MyUser$MyMonday$rdlUser$2\&#39;,\&#39;\&#39;)&#39;, 0)" /><label for="ctl00_ContentPlaceHolder1_MyUser_MyMonday_rdlUser_2">Leave</label></span></td>
</tr><tr>
    <td><span class="available"><input id="ctl00_ContentPlaceHolder1_MyUser_MyMonday_rdlUser_3" class="Available" type="radio" name="ctl00$ContentPlaceHolder1$MyUser$MyMonday$rdlUser" value="SLOT04" checked="checked" /><label for="ctl00_ContentPlaceHolder1_MyUser_MyMonday_rdlUser_3">Available</label></span></td>
</tr>

Update 2

I am stuck here -- I need to point this.ClientID of RadioButtonList to $this of jQuery. Thats it. There by I can execute the 2nd Answer provided by @smoksnes

Update 3

If user selects "Not Available" or "Leave" then it should throw error message as "Do you want to take Leave?" and if he selects "Cancel", then the selection of RadioButtonList should point out to "Available". Otherwise it should select "Not Available" or "Leave" accordingly.

like image 545
CPK_2011 Avatar asked Oct 07 '16 12:10

CPK_2011


1 Answers

Since you're open to the idéa of moving the code to the client instead. Remove the OnSelectedIndexChange on your radiobutton to skip the postback. You should be able to do something like this instead:

// Put this in a script-tag.
$(document).ready(function(){
    $('#<%=this.ClientID%>').change(function(){
        var radioBtnId = this.id;
        radconfirm('Are you sure you want to take leave?', function(arg){
            if (arg == true) {
                alert("User has selected Leave.")
            }    
            else {
                var rdlUser = docment.getElementById(radioBtnId);
                var radioButtons = rdlUser.getElementsByTagName('input');
                radioButtons[1].checked = true;
            }
         }
        });
    });
})

Below is a snippet that uses id's without server code.

$('#radio1').change(function(e){
  var radioBtnId = this.id;
  var $this = $(this);
  radconfirm('Are you sure you want to take leave?', function(arg){
    // Not really sure what you want to do here...
    if (arg == true) {
      alert("User has selected Leave.")
    }    
    else {
      // Select "Available instead".
      $this.siblings('input').prop('checked',true);
      
      // Unselect "Leave"
      
      // With javascript
      var rdlUser = document.getElementById(radioBtnId);              
      rdlUser.checked = false;
      
      // With jQuery
      $this.prop('checked', false);
    }
  });
});
    
// Mocked for now...
function radconfirm(value, callback){
  var result = confirm(value);
  callback(result);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="radio" name="radios" id="radio1" value="Leave"/> <label for="radio1" >Leave</label>
<input type="radio" name="radios" id="radio2" value="Available"/> <label for="radio2" >Available</label>

UPDATE: I've updated the script to fit the new HTML. Here we bind the event to the monday control instead. Note that you might want to set a CssClass on your control instead of using ID. Then you can use the same script for all your controls (MyMonday, MyTuesday etc). It would look something like this:

<asp:MyControl CssClass="day-control" runat="server" id="MyMondayControl" />

If so, you should be able to change the script below to start with:

$('.day-control input').change....

Otherwise you need to use the clientID.

$('#<% MyMondayControl.ClientID %> input').change ....

Don't know why onclick="javascript:setTimeout" is getting added for the HTML

That's because you are using server controls with AutoPostBack for your radiobuttons. Remove that and you should be fine. Read more about it in this question.

In the snippet below I've taken the liberty to assign to CSS-classes to the different radiobuttons. One will determine when to run the "check if leave"-script. And one is for knowing which radiobutton to select if the user chooses to stay. The css classes are leave-check and select-if-not-leave. You can add them with the CssClass property.

You might also want to check what HTML is rendered. The HTML you provided is using table with tr, so just make sure that the css-class is actually rendered on the input. Otherwise you will need to adjust the selector.

// Change to the id of the table instead. Something like:
// $('#<% MyMondayControl.ClientID %> input').change ....

// Here I just the ID generated in the HTML, but you shouldn't use that one.
$('#ctl00_ContentPlaceHolder1_MyUser_MyMonday_rdlUser span.leave input').change(function(e){
  e.preventDefault();
  var radioBtnId = this.id;
  var $this = $(this);
  radconfirm('Are you sure you want to take leave?', function(arg){
    // Not really sure what you want to do here...
    if (arg == true) {
      alert("User has selected Leave.")
    }    
    else {
      // Select "Available instead".
      // Here we use the css class "select-if-not-leave" to find the element which should be selected if the user decides to stay.
      var $parent = $this.closest('table') // Get the table. 
      
      // Select the available input.
      $parent.find('span.available input').prop('checked',true);
      
      // Unselect "Leave" With javascript
      var rdlUser = document.getElementById(radioBtnId);              
      rdlUser.checked = false;
      
      // Unselect "Leave" With jQuery (You only need one)
      $this.prop('checked', false);
    }
  });
});
    
// Mocked for now...
function radconfirm(value, callback){
  var result = confirm(value);
  callback(result);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="ctl00_ContentPlaceHolder1_MyUser_MyMonday_rdlUser">
  <tr>
    <tr>
    <td><span class="leave"><input id="ctl00_ContentPlaceHolder1_MyUser_MyMonday_rdlUser_0" type="radio" name="ctl00$ContentPlaceHolder1$MyUser$MyMonday$rdlUser" value="SLOT01" disabled="disabled"  /><label for="ctl00_ContentPlaceHolder1_MyUser_MyMonday_rdlUser_0">Not Applicable</label></span></td>
    <td><span class="leave"><input id="ctl00_ContentPlaceHolder1_MyUser_MyMonday_rdlUser_1" class="Leave" type="radio" name="ctl00$ContentPlaceHolder1$MyUser$MyMonday$rdlUser" value="SLOT02" /><label for="ctl00_ContentPlaceHolder1_MyUser_MyMonday_rdlUser_1">Not Available</label></span></td>
</tr><tr>
    <td><span class="leave"><input id="ctl00_ContentPlaceHolder1_MyUser_MyMonday_rdlUser_2" class="Leave" type="radio" name="ctl00$ContentPlaceHolder1$MyUser$MyMonday$rdlUser" value="SLOT03"/><label for="ctl00_ContentPlaceHolder1_MyUser_MyMonday_rdlUser_2">Leave</label></span></td>
</tr><tr>
    <td><span class="available"><input id="ctl00_ContentPlaceHolder1_MyUser_MyMonday_rdlUser_3" class="Available" type="radio" name="ctl00$ContentPlaceHolder1$MyUser$MyMonday$rdlUser" value="SLOT04" checked="checked" /><label for="ctl00_ContentPlaceHolder1_MyUser_MyMonday_rdlUser_3">Available</label></span></td>
</tr>
</table>

UPDATE 2:

  1. When I write jQuery script in Day UserControl, then I can use only .leave and .available classes but not .day-control. 2. When I write the jQuery script in UserControl where MyMonday, MyTuesday,... MyFriday are declared, then I can use only .day-control but not .leave and .available classes. @smoksnes Please address this ambiguity.

Where you put you script does not matter, as long as the script looks the same. Preferably, you should put it in a js-file together with your other scripts. Here's a little info how the script and jQuery selectors works:

If you use .day-control span.available input it will first look for a some element with the css class day-control, and a element that is a span WITH css-class available, and lastly an input under the span. If there are several elements that fulfills the criterias I just mentioned it will return all these elements. This script should only be rendered once, since it will capture the events for all your DayUserControl, since they all share the same css class day-control.

However, if you use #<%=this.ClientID%> span.leave input it will start by looking for the element with the specific id (this.ClientID) and there should be only one of those. That is why you need to render that particular script once for every DayUserControl, since it will be unique for that specific user control.

like image 188
smoksnes Avatar answered Oct 14 '22 18:10

smoksnes