通过使用RichFaces使用AJAX调用的支持bean方法动态显示/隐藏页面元素

时间:2014-12-11 18:51:07

标签: jsf richfaces ajax4jsf

我正在尝试实现一个页面,该页面根据输入上的key up事件触发的backing bean方法的结果显示/隐藏元素。我写的内容非常出乎意料 - 我的panelGroup中的内容在页面加载后根本不会改变,而是在页面顶部出现一个包含我期望在outputText元素中显示的内容的狂野跨度。这是在JSF 1.2和richfaces 3.3上运行的遗留应用程序,因此可能无法使用此功能(见here)。我也为表的使用道歉,但遗憾的是重构这个大的旧应用程序以使用适当的布局与css / divs超出了这个功能请求的范围。

这是我的示例jstl模板,它说明了问题。 “string1 / 2颠倒”输出面板应仅显示字符串长度是否大于5,并且输入时输入时应更新outputText元素中的文本。相反,outputPanel保持静态,并在表格上方创建新的范围。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:c="http://java.sun.com/jstl/core" 
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:a4j="http://richfaces.org/a4j"
      xmlns:rich="http://richfaces.org/rich">
    <head>
        <title>ajax test</title>
    </head>
    <body>
        <h:panelGroup id="wrapper">
            <a4j:keepAlive beanName="AjaxTestBacking" />
            <p />
            <h:form>
                <table>
                    <tr>
                        <td >string1:</td>
                        <td>
                            <h:inputText style="width: 200px" value="#{AjaxTestBacking.string1}">
                                <a4j:support event="onkeyup" action="#{AjaxTestBacking.updateString1}" reRender="string1panel"/>
                            </h:inputText>
                        </td>
                    </tr>
                    <h:panelGroup id="string1panel" rendered="#{AjaxTestBacking.displayString1Xform}">
                        <tr>
                            <td>string1 reversed:</td>
                            <td>
                                <h:outputText style="width: 200px" value="#{AjaxTestBacking.string1Xform}" />
                            </td>
                        </tr>
                    </h:panelGroup>                  
                    <tr>
                        <td>string2:</td>
                        <td>
                            <h:inputText style="width: 200px" value="#{AjaxTestBacking.string2}">
                                <a4j:support event="onkeyup" action="#{AjaxTestBacking.updateString2}" reRender="string2panel"/>
                            </h:inputText>
                        </td>
                    </tr>
                    <h:panelGroup id="string2panel" rendered="#{AjaxTestBacking.displayString2Xform}">
                        <tr>
                            <td>string2 reversed:</td>
                            <td >
                                <h:outputText style="width: 200px" value="#{AjaxTestBacking.string2Xform}" />
                            </td>
                        </tr>
                    </h:panelGroup>
                </table>
            </h:form>
        </h:panelGroup>
    </body>
</html>

和支持bean:

import java.io.Serializable;

@SuppressWarnings("serial")
public class AjaxTestManager extends AbstractManager implements Serializable {

    private String string1;
    private String string2;

    private String string1Xform;
    private String string2Xform;

    private Boolean displayString1Xform;
    private Boolean displayString2Xform;

    public AjaxTestManager() {
        string1 = "test string 1";
        string2 = "test string 2";
        updateString1();
        updateString2();
    }

    public void updateString1() {
        string1Xform = new StringBuilder(string1).reverse().toString();
        displayString1Xform =string1Xform.length() > 5 ? true : false;
    }

    public void updateString2() {
        string2Xform = new StringBuilder(string2).reverse().toString();
        displayString2Xform = string2Xform.length() > 5 ? true : false;
    }

    public String getString1() {
        return string1;
    }

    public void setString1(String string1) {
        this.string1 = string1;
    }

    public String getString2() {
        return string2;
    }

    public void setString2(String string2) {
        this.string2 = string2;
    }

    public String getString1Xform() {
        return string1Xform;
    }

    public void setString1Xform(String string1Xform) {
        this.string1Xform = string1Xform;
    }

    public String getString2Xform() {
        return string2Xform;
    }

    public void setString2Xform(String string2Xform) {
        this.string2Xform = string2Xform;
    }


    public Boolean getDisplayString1Xform() {
        return displayString1Xform;
    }


    public void setDisplayString1Xform(Boolean displayString1Xform) {
        this.displayString1Xform = displayString1Xform;
    }


    public Boolean getDisplayString2Xform() {
        return displayString2Xform;
    }


    public void setDisplayString2Xform(Boolean displayString2Xform) {
        this.displayString2Xform = displayString2Xform;
    }

}

如果我在这里从根本上误解了有关richfaces的内容,我道歉 - 我有点喜欢富有表面的ajax,所以请耐心等待!我与构建应用程序的同事分享了这段代码,他也很难过。我在google和SO上搜索并找到了一个基于javascript的答案,但我试图了解如何使用richfaces组件来做到这一点。其他问题:“呈现”属性是否可以通过动态显示/隐藏页面部分来实现,或者我应该使用“可见”属性?另外,是a4j上的'reRender'属性:支持应该是我最初理解的元素的jsf /'服务器端'id,还是所示的呈现的客户端元素ID here?只是想弄清楚我是否误解了某些东西,受到我的jsf / richfaces版本的限制,或者只是一般都疯了:)

1 个答案:

答案 0 :(得分:0)

我见过与JSF 2.1类似的行为。如果某个元素上存在呈现的标记,并且您计划通过ajax显示/隐藏该元素,则应该使用另一个命名容器将其包装并重新呈现父容器。这样的事情可以做到

                  <tr>
                    <td >string1:</td>
                    <td>
                        <h:inputText style="width: 200px" value="#{AjaxTestBacking.string1}">
                            <a4j:support event="onkeyup" action="#{AjaxTestBacking.updateString1}" reRender="string1panelLabel,string1panelValue"/>
                        </h:inputText>
                    </td>
                </tr>
                    <tr>
                        <td>                    
                          <h:panelGroup id="string1panelLabel">
                            <h:panelGroup rendered="#{AjaxTestBacking.displayString1Xform}">
                              string1 reversed:
                            </h:panelGroup>
                          </h:panelGroup>                                          
                       </td>
                        <td>
                          <h:panelGroup id="string1panelValue">
                            <h:panelGroup rendered="#{AjaxTestBacking.displayString1Xform}">
                                <h:outputText style="width: 200px" value="#{AjaxTestBacking.string1Xform}" />
                            </h:panelGroup>
                          </h:panelGroup>                                                                        
                        </td>
                    </tr>

                <tr>

请注意,panelGroup在这里渲染一个span,结果不是合法的html,因为tr标签之间不能存在span。相反,panelGroup应该在表中的td标记内。因此,您必须有两组嵌套的panelGroup来解决问题。或者,你可以用h:panelGrid替换html表,它生成一个html但对JSF更友好。

作为旁注,我在JSF 2.1中使用ui:fragment,因为它使得显示/隐藏屏幕的这一部分的意图比panelGroup更明显。