RadioButtonList不总是触发SelectedIndexChanged事件

9

我有一个RadioButtonList,其中包含“不适用”,“不可用”,“请假”和“可用”选项。

  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.

以下是JavaScript代码,用于“确定”或“取消”离开。
    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;
        }
    }

如果用户第二次点击"离开",SelectedIndexChanged将完全不触发。

我可以考虑将服务器端代码移动到客户端。

更新

以下是相关的HTML代码。

<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>

更新2

我陷入了困境-- 我需要将 RadioButtonList 的 this.ClientID 指向 jQuery 的 $this。这样就可以执行 @smoksnes 提供的第二个答案。

更新3

如果用户选择“不可用”或“请假”,则应抛出错误消息“您想请假吗?”如果他选择“取消”,则 RadioButtonList 的选择应指向“可用”。否则,它应相应地选择“不可用”或“请假”。


可能是因为单选按钮在第一次点击后仍保持选中状态。这意味着第二次单选按钮的值不会改变。如果用户没有确认,请尝试将值更改回“可用”。 - Lidaranis
这是我现在正在做的事情 var rdlUser = docment.getElementById("<%= rdlUser.ClientID %>"); var radioButtons = rdlUser.getElementsByTagName('input'); radioButtons[1].checked = true; 在 confirmLeave 的 else 部分。 - CPK_2011
尝试在客户端上使用事件监听器,而不是进行回发。类似这样:$('#<%=this.ClientID%>').change(function(){//code here}); - smoksnes
你能否详细说明一下? - CPK_2011
@CPK_2011 - 是的,我把它发布为答案,因为它太长了,不适合作为评论。如果我误解了问题,请告诉我。 - smoksnes
2个回答

2
既然您愿意将代码移动到客户端,那么可以尝试删除单选按钮的OnSelectedIndexChange以跳过回传。您应该能够像这样做:
// 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;
            }
         }
        });
    });
})

下面是一个使用ID但没有服务器代码的片段。

$('#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>

更新: 我已经更新了脚本以适应新的HTML。在这里,我们将事件绑定到星期一控件上。请注意,您可能希望在控件上设置{{link1:CssClass}},而不是使用ID。然后,您可以将相同的脚本用于所有控件(MyMonday、MyTuesday等)。它会看起来像这样:
<asp:MyControl CssClass="day-control" runat="server" id="MyMondayControl" />

如果是这样,您应该能够更改下面的脚本以开始:
$('.day-control input').change....

否则,您需要使用clientID。
$('#<% MyMondayControl.ClientID %> input').change ....

“不知道为什么HTML中会加入onclick="javascript:setTimeout"。” 这是因为您正在使用AutoPostBack的服务器控件来控制单选按钮。移除这个属性后,就能正常工作了。在这个问题中可以找到更多相关信息。
在下面的代码片段中,我已经自己给不同的单选按钮分配了CSS类。其中一个用于运行“检查是否离开”的脚本,另一个用于判断如果用户选择留下应该选择哪个单选按钮。这两个CSS类分别是leave-checkselect-if-not-leave,您可以使用CssClass属性添加它们。
您可能还想检查渲染的HTML。您提供的HTML使用tabletr,因此请确保css类实际上呈现在input上。否则,您将需要调整选择器。

// 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>

更新2:
  1. 当我在Day UserControl中编写jQuery脚本时,我只能使用.leave和.available类,而不能使用.day-control。 2. 当我在UserControl中编写jQuery脚本时,其中声明了MyMonday,MyTuesday,... MyFriday,那么我只能使用.day-control,而不能使用.leave和.available类。@smoksnes请解决这种歧义。
无论您将脚本放在何处,只要脚本看起来相同即可。最好将其与其他脚本一起放在js文件中。以下是有关脚本和jQuery选择器如何工作的一些信息:
如果您使用.day-control span.available input,它将首先查找具有css类day-control的某个元素,以及带有css类available元素,并在下面找到input。如果有多个元素符合我刚才提到的标准,它将返回所有这些元素。此脚本应仅呈现一次,因为它将捕获所有DayUserControl的事件,因为它们都共享相同的css类day-control
然而,如果您使用#<%=this.ClientID%> span.leave input,它将从具有特定idthis.ClientID)的元素开始查找,应该只有一个这样的元素。这就是为什么您需要为每个DayUserControl呈现特定脚本一次,因为它将是该特定用户控件的唯一脚本。

你实现的所有代码放在客户端这一观点我不太满意。它在这里使用"运行代码片段"是可以工作的。但是我需要正确的捕获change事件的方式。你能重新审视我的问题吗?我是从服务器端触发rdlUser_SelectedIndexChanged,然后在JavaScript中正确地捕获它。我尝试在else部分放置$this.siblings('input').prop('checked', true); var rdlAvailability = document.getElementById(radioBtnId); rdlAvailability.checked = false; $this.prop('checked', false);,但这并不起作用。需要一种新的或修改过的方法。 - CPK_2011
我有5个用户控件(MyMonday,MyTuesday.. MyFriday)放置在1个名为MyUser的用户控件中,并将此用户控件放置在aspx页面中。对于当前情况,我仅提供了MyMonday。对于每一天,它都包含4个名为“SLOT0”,“SLOT01”,“SLOT03”和“SLOT04”的RadioButtonList插槽,问题中也提供了相同的内容。 - CPK_2011
请查看问题中的第三个更新。 - CPK_2011
@CPK_2011 - 我已经再次更新了代码片段。CSS选择器是区分大小写的,如果你在HTML中更改了CSS类,那么你也需要在JavaScript中进行更改。 - smoksnes
代码片段可行吗?请检查我在最后一次编辑中所做的更改。CssClass 现在应该是´leave`,区分大小写。 - smoksnes
显示剩余15条评论

0

将调用者对象传递给radconfirm函数。(http://docs.telerik.com/devtools/aspnet-ajax/controls/window/alert,-confirm,-prompt-dialogs/radconfirm-dialog)。

从服务器传递调用者对象 protected void rdlUser_SelectedIndexChanged(object sender, EventArgs e) { //var oConfirm = radconfirm(text, callBackFn, oWidth, oHeight, callerObj, oTitle, imgUrl); radWindowManager.RadConfirm("你确定要请假吗?", "confirmLeave", 300, 100, null, ""); }

一个JavaScript函数来验证列表中的所有控件。

function confirmLeave(arg) { if (arg == true) { alert("用户已选择离开。") }
else { //获取调用者ID并验证 var rdlUser = docment.getElementById("<%= rdlUser.ClientID %>"); var radioButtons = rdlUser.getElementsByTagName('input'); radioButtons[1].checked = true; } }

我参考了文档,但没有测试这段代码,希望这可以帮到您。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接