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

标签 ajax jsf-2

我有一个要显示的嵌套问题列表。最初,我显示 1 级问题,然后根据用户对其父问题的回答显示子问题。所有问题都有一个单选按钮,一些问题有一个输入框,用于在用户选择"is"时显示附加信息

这是我的带有嵌套数据表的 JSF 代码。请注意,为了简化论坛上的问题,我已经删除了这些问题的格式,因此如果您将此代码复制到您自己的环境中并运行代码,这些问题可能看起来“不漂亮”:

<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 上的重置函数的代码:

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”。如果我点击"is"然后再次点击"is",ajax 调用应该不会发生,对吗?但它是,因为附加信息框正在根据重置功能清除。

我最初尝试向重置函数添加一个条件以检查被单击的按钮的值,并且仅在答案为“0”(否)时重置 addnInfo 值和子问题。但这会导致呈现出现问题,因为 ajax 调用会呈现输入框和子问题以隐藏并且值将保留在前端,即使它们在支持 bean 上被重置。当它们重新呈现到前端时,显示的是保留的值,而不是 backing bean 中的值。

另一个尝试是使用 ValueChangeListener 来重置值。但这仍然存在与重新渲染时保留的值相同的问题。

我尝试了 3 种不同的方法(上面列出的),但都失败了。我愿意听取任何这些解决方案或可能是其他解决方案的解决方案。请记住,用户的格式限制使我可以使用的选项更少。

最佳答案

Ajax Listener event valueChange seems to be firing onClick instead of onChange

这确实是默认值 valueChange由各个 JSF 组件生成的单选按钮和复选框使用的事件。检查生成的 HTML 源代码,您会发现它已挂接到 onclick。 .默认情况下 JSF 这样做的原因对于复选框是明确的,但乍一看对于单选按钮并不完全清楚,因为它们无论如何都不能取消选中。真正的原因是为了保证IE6/7的兼容性才做的onchange在该浏览器中第一次点击时不会触发。

如果您不关心 IE6/7 用户(但最近其分布急剧下降),则将其更改为 event="change"反而。

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

这样 JSF 将在 onchange 上生成事件处理程序反而。


更新:你可以使用jQuery.on('change')函数绑定(bind)器,它将修复 change 上的 IE6/7 错误行为事件。在 <h:head> 中包含以下内容如果您还没有使用 jQuery:

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

并在加载时执行此函数:

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

这基本上会为每个单选按钮移动 JSF 生成的 onclick属性为 change由 jQuery 管理的事件处理程序,因此它可以在所有浏览器中一致地工作,包括 IE6/7。

我们当然也可以使用纯 JS 来完成,但这需要大量样板和跨浏览器敏感代码。

关于Ajax Listener 事件 valueChange 似乎触发了 onClick 而不是 onChange,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8303961/

相关文章:

jsf - 如何使用 p :blockUI with p:tabView

jsf-2 - JSF 2.1 和接缝 : s:token still required

javascript - 在 selectOneMenu 更改时在同一窗口中打开对话框

php - 无法登录 - 并且没有错误消息。 - PHP

javascript - 样式化 json 列表

javascript - jquery ajax超时最佳实践值

java - 为什么这个表格内嵌编辑器不起作用?

xpath - 使用 Selenium Webdriver+Java 的 primefaces selectOneMenu 值

php - javascript XMLHttpRequest 打开 php 文件并执行更多的 javascript

javascript - jQuery Ajax 返回未定义