Ajax侦听器事件valueChange似乎在触发onClick而不是onChange [英] Ajax Listener event valueChange seems to be firing onClick instead of onChange

查看:66
本文介绍了Ajax侦听器事件valueChange似乎在触发onClick而不是onChange的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想显示一个嵌套的问题列表.最初,我显示的是1级问题,然后根据用户对父级问题的回答显示子问题.所有问题都有一个单选按钮,有些问题有一个输入框,供用户选择是"时显示其他信息.

I have a nested list of Questions that I'd like to display. Initially, I'm displaying the Level 1 questions and then subquestions are displayed based on the users answers to the their parent question. All questions have a radio button and some questions have an input box for additional information that is shown when user selects "Yes"

这是我的带有嵌套dataTables的JSF代码.请注意,我已经取消了这些问题的格式设置,以简化论坛上的问题,因此,如果您将此代码复制到您自己的环境中并运行代码,则这些问题看起来不太漂亮":

Here is my JSF code with nested dataTables. Please note that I have pulled out formatting of these questions in order to simply the question on the forum, so these may look "unpretty" if you copy this code into your own environment and run the code:

<h:dataTable id="questionTable" var="q" value="#{generalQuestionBean2.questions.questions}">
<h:column><h:panelGroup id="questionGrp">
#{q.question} <h:selectOneRadio value="#{q.answer}">
<f:selectItem itemValue="1" itemLabel="Yes"/>
<f:selectItem itemValue="0" itemLabel="No"/>
<f:ajax event="valueChange" execute="@form"
    render="questionGrp"
    listener="#{generalQuestionBean2.reset}"/>
</h:selectOneRadio> <h:inputText value="#{q.addnInfo}"
rendered="#{q.answer eq '1' and q.field ne 'otherCov'}"></h:inputText>

<h:panelGroup id="questionGrpSubs" rendered="#{q.addnQuestions ne null and q.answer eq '1'}">
<h:dataTable id="subQuestionTable" var="subq" value="#{q.addnQuestions}">
<h:column><h:panelGroup id="subQuestionGrp">
->#{subq.question} <h:selectOneRadio id="answer" value="#{subq.answer}"> 
 <f:selectItem itemValue="1" itemLabel="Yes"/>
 <f:selectItem itemValue="0" itemLabel="No"/>
 <f:ajax event="valueChange" execute="@form"
    render="subQuestionGrp"
    listener="#{generalQuestionBean2.reset}"/>
</h:selectOneRadio><h:inputText value="#{subq.addnInfo}"
rendered="#{subq.answer eq '1' and subq.field ne 'voluntaryComp' and subq.field ne 'uslh'}"></h:inputText>

<h:panelGroup id="questionGrpSubs2" rendered="#{subq.addnQuestions ne null and subq.answer eq '1'}">
<h:dataTable id="sub2QuestionTable" var="sub2q" value="#{subq.addnQuestions}">
<h:column><h:panelGroup id="sub2QuestionGrp">
-->#{sub2q.question} <h:selectOneRadio id="answer" value="#{sub2q.answer}"> 
 <f:selectItem itemValue="1" itemLabel="Yes"/>
 <f:selectItem itemValue="0" itemLabel="No"/>
 <f:ajax event="valueChange" execute="@form"
    render="sub2QuestionGrp"
    listener="#{generalQuestionBean2.reset}"/>
</h:selectOneRadio><h:inputText value="#{sub2q.addnInfo}"
rendered="#{sub2q.answer eq '1'}"></h:inputText>

</h:panelGroup></h:column>
</h:dataTable></h:panelGroup>
</h:panelGroup></h:column>
</h:dataTable></h:panelGroup>
</h:panelGroup></h:column>
</h:dataTable>

以下是备用Bean上的reset函数的代码:

Here is the code for the reset function on the backing bean:

private void reset(AjaxBehaviorEvent event) {
    FacesContext context = FacesContext.getCurrentInstance();
    String id = event.getComponent().getClientId(context);
    String[] tokens = id.split("[:]+");
    int qId = -1;
    int subqId = -1;
    int sub2qId = -1;
    for (int i = 0; i < tokens.length; i++) {
        if(tokens[i].equals("questionTable")) 
            qId = Integer.parseInt(tokens[i+1]);
        if(tokens[i].equals("subQuestionTable"))
            subqId = Integer.parseInt(tokens[i+1]);
        if(tokens[i].equals("sub2QuestionTable"))
            sub2qId = Integer.parseInt(tokens[i+1]);

    }
    Question q = questions.getQuestion(qId);
    Question processQ = q;
    String defaultSubAnswer = getDefaultSubAnswer(q.getField());
    Question subq;
    Question subq2;
    if(subqId > -1) {
        subq = q.getAddnQuestions().get(subqId);
        processQ = subq;
        if(sub2qId > -1) {
            subq2 = subq.getAddnQuestions().get(sub2qId);
            processQ = subq2;
        }
    }
    resetValue(processQ, defaultSubAnswer);
}


private void resetValue(Question q, String defaultSubAnswer) {
    q.setAddnInfo("");
    if(q.getAddnQuestions() != null) {
        for (int i = 0; i < q.getAddnQuestions().size(); i++) {
            Question subq = q.getAddnQuestions().get(i);
            subq.setAnswer(defaultSubAnswer);
            resetValue(subq, defaultSubAnswer);
        }
    }
}

问题出在这里

ajax事件应默认为"valueChange".如果我单击是",然后再次单击是",则应该不会进行ajax调用,对吗?但是是这样,因为附加信息"框正在基于重置功能清除.

The ajax event should default to "valueChange". If I click on "Yes" and then "Yes" again, the ajax call should not happen, correct? But it is, as the Additional Info box is clearing out based on the reset function.

我最初尝试向重置功能添加条件以检查所单击按钮的值,并且仅在答案为"0"(否)的情况下重置addnInfo值和子问题.但是,这导致了渲染问题,因为ajax调用会隐藏输入框和子问题,并且即使在后备bean上重置了值,值也会保留在前端.当它们重新渲染到最前面时,显示的是保留的值,而不是后备bean中的值.

I had originally tried adding a condition to the reset function to check the value of the button that was clicked and only reset the addnInfo value and subquestions if the answer is "0" (No). But this was causing issues with the rendering as the ajax call would render the input box and subquestions to hide and the value would be held onto on the front end, even though they're reset on the backing bean. When they re-rendered to the front in, the value that was held onto shows up instead of the value in the backing bean.

另一种尝试是使用ValueChangeListener重置值.但这仍然存在相同的问题,即重新渲染时保留值.

Another attempt was using a ValueChangeListener for the reset of the values. But this still has the same issue with the value being held onto when re-rendering.

我尝试了3种不同的方法(上面列出),但都失败了.我乐于听取任何一种解决方案,也可能是另一种解决方案.请记住,用户的格式限制使我只能选择更少的选项.

I have tried 3 different approaches (listed above) and all have failed. I'm open to hearing a solution to any of these or possibly another solution. Keep in mind that formatting limitations by the users leaves me with less options to work with.

推荐答案

Ajax Listener事件valueChange似乎触发了onClick而不是onChange

这确实是默认的valueChange事件,由相应的JSF组件生成的单选按钮和复选框使用.检查生成的HTML源,您将看到它已被链接到onclick.对于复选框,JSF默认情况下会执行此操作的原因是明确的,但是乍一看,对于单选按钮而言,这并不是完全清楚的,因为无论如何它们都不会被选中.真正的原因是这样做是为了确保IE6/7兼容性,因为onchange不会在该浏览器中的第一次单击时被触发.

That's indeed the default valueChange event which is been used by the radio buttons and checkboxes which are genreated by the respective JSF components. Check the generated HTML source and you'll see that it's hooked to onclick. The reason why JSF does that by default is clear for checkboxes, but at first sight not entirely clear for radio buttons as they cannot be unticked anyway. The real reason is that it's done in order to ensure IE6/7 compatibility as onchange wouldn't be fired on 1st click in that browser.

如果您不关心IE6/7用户(其分布最近逐渐减少),则将其更改为event="change".

If you don't care about IE6/7 users (whose distribution is however stongly decreasing lately), then change it to event="change" instead.

<f:ajax event="change" ... />

这样,JSF将改为在onchange上生成事件处理程序.

This way JSF will generate the event handler on onchange instead.

更新:您可以使用 jQuery .on('change')函数绑定器来修复IE6/7在change事件上的行为异常.如果您尚未使用jQuery,请在<h:head>中添加以下内容:

Update: you could use jQuery's .on('change') function binder which will fix the IE6/7 misbehaviour on the change event. Include the following in <h:head> if you're not already using jQuery:

<script src="http://code.jquery.com/jquery-latest.min.js"></script>

并在加载时执行此功能:

and execute this function on load:

$(function() {
    $(':radio').each(function() {
        var handler = this.onclick;
        this.onclick = null;
        $(this).on('change', handler);
    });
});

基本上,这将使每个单选按钮将JSF生成的onclick属性移动到change事件处理程序,该事件处理程序由jQuery管理,以便在包括IE6/7在内的所有浏览器中正常工作.

This will basically for every radio button move the JSF-generated onclick attribute to change event handler which is managed by jQuery so that it works consitent in all browsers, including IE6/7.

我们当然也可以使用普通的JS来做到这一点,但这需要大量样板代码和跨浏览器的敏感代码.

We can of course also do it with plain JS, but that would require lot of boilerplate and cross browser sensitive code.

这篇关于Ajax侦听器事件valueChange似乎在触发onClick而不是onChange的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆