JSF视图未使用AJAX更新

时间:2013-11-25 11:12:54

标签: ajax jsf-2 primefaces

我正在尝试使用JSF 2.2和PrimeFaces 4.0创建可更新的GUI。我的问题是模型已更新,但视图不是。

这是我的示例页面。它只有一个按钮,可以让两个面板改变它们的位置:

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:p="http://primefaces.org/ui">
    <h:head/>
    <h:body>
        <h:form>
            <p:panelGrid id="grid">
                <p:row>
                    <p:column id="slot1" style="width: 100px; height: 100px">
                        <p:panel id="panel1" binding="#{test.panel1}" style="width: 100px; height: 100px"/>
                    </p:column>
                    <p:column id="slot2" style="width: 100px; height: 100px">
                        <p:panel id="panel2" binding="#{test.panel2}" style="width: 100px; height: 100px"/>
                    </p:column>
                </p:row>
            </p:panelGrid>

            <p:commandButton id="button2" value="Switch Panels">
                <p:ajax listener="#{test.onSwitchPanels(event)}" update="grid"/>
            </p:commandButton>
        </h:form>
    </h:body>
</html>

Java类:

@ManagedBean
@SessionScoped
public class Test {

Panel panel1 = new Panel();
Panel panel2 = new Panel();

public Test() {
    panel1.setHeader("Panel 1");
    panel2.setHeader("Panel 2");
}

public Panel getPanel1() {
    return panel1;
}

public void setPanel1(Panel panel) {
    this.panel1 = panel;
}

public Panel getPanel2() {
    return panel2;
}

public void setPanel2(Panel panel) {
    this.panel2 = panel;
}

public void onSwitchPanels(ActionEvent event) {
    Panel tmp = panel1;
    panel1 = panel2;
    panel2 = tmp;
}
}

调试显示,当单击按钮时,onSwitchPanels()之后使用正确的新值调用getter和setter。 但正如我写的那样,视图没有更新。只有在手动页面刷新或下一次单击后才会发生这种情况(当然,这会将模型设置回原始状态,但会显示切换的面板)。 我已经尝试了update="@form"update="slot1 slot2"但没有运气......

4 个答案:

答案 0 :(得分:2)

这段代码老实说是WTF。将UI组件实例绑定到会话范围的bean是一个麻烦的方法。 UI组件实例即请求范围。

即使您使用了请求范围的bean,这也无法在不重建视图的情况下工作。在构建视图期间创建UI组件树。在构建视图之后,您正在操作组件引用,并期望更改在UI组件树中神奇地反映出来。这不是真的。只会反映他们的属性(因此,当您执行panel1.setHeader(panel2.getHeader())时,反之亦然,那么它就会工作&#34;。

不清楚为什么你在这个方向思考。通常,您应该动态操作模型,而不是视图(UI组件不代表模型,它们代表视图;使模型/控制器的属性不会神奇地使其成为模型)。最直接的方法之一是拥有一个实体列表并将它们呈现在动态<p:dataGrid>中而不是硬编码<p:panelGrid>中,从而根据当前迭代的模型项动态设置所需的组件属性。

E.g。这个

<h:form>
    <p:dataGrid value="#{bean.items}" var="item" columns="2">
        <p:column><p:panel header="#{item.header}" /></p:column>
    </p:dataGrid>
    <p:commandButton value="swap" action="#{bean.swap}" update="grid" />    
</h:form>

@ViewScoped(!)bean中使用它:

private List<Item> items; // +getter

@PostConstruct
public void init() {
    items = new ArrayList<>();
    items.add(new Item("Panel 1"));
    items.add(new Item("Panel 2"));
}

public void swap() {
    items.add(items.remove(0)); // Note: works only if you've only 2 items ;)
}

Item类只是一个具有header属性的javabean。平均IDE可以自动生成整个类。

另见:

答案 1 :(得分:0)

我的JSF / PF有点生疏,但你试过了吗?

update="panel1 panel2"

要尝试的另一件事是使用

actionListener"#{test.onSwitchPanels}"

而不是

listener="#{test.onSwitchPanels(event)}"

答案 2 :(得分:0)

为什么不从onSwitchPanels()方法中删除'event'参数?你没有以任何方式使用它。你可以通过

解雇它
<p:commandButton id="button2" value="Switch Panels" action="#{test.onSwitchPanels}" update="grid" />

答案 3 :(得分:0)

我找到了采用此示例的解决方案:http://www.wobblycogs.co.uk/index.php/computing/jee/70-dynamic-dashboard-with-primefaces-part-2

重点是以编程方式创建组件。在JSF页面中,我只需编写类似<p:panelGrid id="grid" binding="#{gridBacker.grid}"/>的内容,并使用bean使用Application.createComponent()创建行,列和面板。事件发生后,小组将再次加入。

当然,BalusC是正确的,必须在模型中进行。