JSF2“f:ajax render”呈现的内容超过了指定的id

时间:2011-07-06 14:34:54

标签: java ajax jsf jsf-2 render

我在这里和网上搜索并尝试了各种各样的东西; prependId,使用完整的id路径(:form:panelid:componentid kinda thing)和其他路径。

我仍然感到困惑。我还是一个JSF菜鸟:)

我的问题是,我在f:ajax渲染部分中指定的不是唯一部分得到“执行”。我的意思是,渲染中指定的id不会在屏幕上重新呈现,但会调用该组件的值。

所以:

inputText的f:ajax render = outA event = blur

当模糊发生时,调用outA的getter并重新渲染,但也会调用其他组件的getter,但它们不会被重新渲染。

具体而言,根据下面列出的代码:

A)当val1失去焦点时,它会触发模糊事件,它会调用getValue1()并重新渲染outval1。快乐。但是,getStuff()也被调用(它也适用于其他模糊和btnCalc)但是getStuff()的结果不会呈现给tblStuff dataTable。 为什么呢?

如何修复它,以便在blur事件中,只执行与render =“..”组件相关的getter?

我应该使用不同的部分吗?

B)当点击刷新按钮时,它将调用getStuff AGAIN,现在显示新的dataTable /即具有在模糊事件和btnReload点击事件期间添加的所有多个ValueTO的新数据。

C)对于在A中命名的任何一个事件,getStuff方法被正好调用8次。即,在输入框内单击,单击外部输入框,getStuff()* 8。 然而,getValue1只被调用了两次?

D)那里有任何好的JSF2书籍吗?

以下是页面:

<?xml version="1.0" encoding="UTF-8" ?>
<!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:f="http://java.sun.com/jsf/core">

<h:head>
    <title>Stuff</title>
</h:head>
<h:body>
        <h:form id="frmTrxMain" prependId="true">

            <h1>
                Stuff
            </h1>

            <h:dataTable title="Stuff" id="tblStuff" var="s" value="#{bean.stuff}" border="1">

                <h:column>
                    <f:facet name="header">
                        <h:outputText value="ID" />
                    </f:facet>
                    <h:outputText value="#{s.id}"/>
                </h:column>

                <h:column>
                    <f:facet name="header">
                        <h:outputText value="Name" />
                    </f:facet>
                    <h:outputText value="#{s.name}" />
                </h:column>

            </h:dataTable>

            <h:outputText value="No stuff to display" rendered="#{empty bean.stuff}"/>
            <h:commandButton value="Refresh" id="btnReload">
                <f:ajax render="tblStuff" event="click"/>
            </h:commandButton>

            <hr/>

            <h:panelGrid columns="3" id="pnlTwo">
                <h:outputLabel value="Value1"/>
                <h:inputText value="#{bean.value1}" id="val1">
                    <f:ajax event="blur" render="outVal1"/>
                </h:inputText>
                <h:outputText id="outVal1" value="Entered: #{bean.value1}" />

                <h:outputLabel value="Value2"/>
                <h:inputText value="#{bean.value2}" id="val2">
                    <f:ajax event="blur" render="outVal2"/>
                </h:inputText>
                <h:outputText id="outVal2" value="Entered: #{bean.value2}" />

                <h:commandButton value="Calc" id="btnCalc"> 
                  <f:ajax event="click" render="outSum"/> 
                </h:commandButton> 
            </h:panelGrid>

            <h:outputLabel id="outSum" value="#{bean.sum}"/>
        </h:form>
</h:body>
</html>

支持bean:

import java.util.ArrayList;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean(name = "bean")
@SessionScoped
public class TestStuffBean {

private int id=1;
private String name="a";
//test.xhtml
private String value1;
private String value2;

private List<TestVO> stuff = new ArrayList<TestVO>();

public String getValue1() {
    return value1;
}

public void setValue1(String value1) {
    this.value1 = value1;
}

public String getValue2() {
    return value2;
}

public void setValue2(String value2) {
    this.value2 = value2;
}

public String getSum() {

    String result = "";

    int sum;
        try {
            sum = Integer.parseInt(value1) + Integer.parseInt(value2);
            result = Integer.toString(sum);
        } catch (NumberFormatException e) {
            result = "Enter two integers";
        }

    return result;
}

public List<TestVO> getStuff() {
    //the VO is just a POJO with a contructor that takes 
            //two strings and a getter/setter for each id and name
        stuff.add(new TestVO(Integer.toString(id), name+id));
        id++;

    return stuff;
}
}

1 个答案:

答案 0 :(得分:0)

我不是JSF 2专家,因为我们仍在使用1.2但是我猜他们在这里有相同的属性:经常调用getter,例如在还原视图阶段重建视图时。因此,您不能仅依赖于仅为实际渲染的部件调用的getter。事实上,你不应该在你的getter中做任何昂贵的操作(比如db访问) - 在大多数情况下你不知道它们在一个循环中实际被调用的频率。

特别是你的getStuff()方法应该改变,让一个getter引起副作用,例如添加到内部列表中的东西,就像在这种情况下一样,也几乎总是糟糕的设计。

编辑:澄清对getter的评论:

通常情况下,getter不应该执行昂贵的操作,因为您不知道JSF调用它们的频率。 由于您仍然需要从某些源(如数据库)获取某些数据,因此您可能只提供方法(如loadDataFromDB())并填充托管bean中的某些数据结构。然后,getter可能只是提供该数据结构。

您可以添加对未初始化的数据结构的检查,如果没有在getter中调用load方法,但我只将其用作最后一个选项。通常,您应该能够单独调用加载方法,例如通过单击刷新按钮或导航到页面 - 这就是我们的工作。