Primefaces AJAX无法呈现嵌套的UIComponent且actionListener无效

时间:2016-04-11 16:33:48

标签: ajax jsf-2 primefaces

编辑2:为何与众不同

@BalusC,这与the post you say不同,因为我问的是actionListener奇怪的行为没有执行方法。

此外,在我的测试中,我按照Primefaces的文档,将固定id属性应用于每个NamingContainer并检查生成的HTML(并具有预期的{{1} }}' S)

你说这个帖子与此重复,这是一个很好的帮助,但我们在这里讨论另一个问题。

我正在使用webapp的布局,发现更新DOM时出现问题。我正在使用 Primefaces 5.2 Glassfish 4.1 。为了隔离问题,我尝试在其他项目中测试它,但我在测试中发现了另一个问题。也许我错过了什么,所以我需要在这个论坛上提问。

我会倒退:我会描述测试,然后是真正的问题所以你可以看到它具有相同的结构

失败的测试

的index.xhtml

id

renderView.java

<h:body>
  <h:form id="form-render">
    <p:commandButton id="btnRender" value="Render" update=":form-rendered"
                     actionListener="#{renderView.setRender(true)}"/>
  </h:form>

  <h:form id="form-rendered">
    <h:outputText value="Rendered in form-rendered" rendered="#{renderView.render}"/>

    <p:panelGrid id="panel-grid" rendered="#{renderView.render}">
      <p:outputLabel value="Rendered in form-rendered:panel-grid"/>
    </p:panelGrid>
  </h:form>
</h:body>

但是当我运行测试时,只渲染import java.io.Serializable; import javax.faces.bean.ManagedBean; import javax.faces.bean.ViewScoped; @ManagedBean @ViewScoped public class RenderView implements Serializable { private static final long serialVersionUID = -1687524798440117276L; private boolean render; public RenderView() { this.render = false; System.out.println("Constructor - render=" + this.render); } public boolean isRender() { return render; } public void setRender(boolean render) { this.render = render; System.out.println("Setter - render=" + this.render); } } 组件。我尝试了另一种选择:

  • <h:outputText>:结果相同
  • update=":form-rendered, :form-rendered:panel-grid":不会渲染任何内容
  • update=":form-rendered:panel-grid"属性从rendered=#{...}移至<p:panelGrid>内:不会更改

我不知道如何引用<p:outputLabel>中的<p:panelGrid>。根据{{​​3}}:

  

Update属性采用逗号或空格分隔的JSF组件ID列表进行更新

所以第一个选项应该有效,但它没有。我在这里缺少什么?

真正的问题

之前的测试来自我面临的布局问题。布局的想法如下:

  • 在几个页面中,我需要搜索一些内容并在搜索表单下显示结果(当然是使用AJAX)。
  • 布局中的每个页面都是<h:form>(由facelet template client制作)
  • 这只是布局,没有任何查询,业务逻辑或类似的东西。我使用的<ui:composition>类只是创建虚拟对象来填充Primefaces的组件

所以我使用了前一个测试的相同结构来解决每个页面中的问题。有趣的是,我编写了第一个并完美地工作,但是当我编写第二个时,无法渲染第二个表单。 更多的是,我编写了第三个并完美地工作,编码第四个并且失败!!!

在我的第一个解决方案尝试中,我使用了以下bean:

@ManagedBean

我首先从一个工作示例中复制粘贴,然后形成一个失败的例子,所以也许你可以看到我失踪的东西。

searchPage1.xhtml(工作)

@ManagedBean // from javax.faces.bean
@ViewScoped  // idem
public class SearchView {
    private boolean showResults;

    public SearchView() {
        this.showResults = false;
        System.out.println("Constructor-showResults=" + this.showResults);
    }

    public boolean isShowResults() {
        return showResults;
    }

    public void setShowResults(boolean showResults) {
        this.showResults = showResults;
        System.out.println("Setter-showResults=" + this.showResults);
    }
}

searchPage2.xhtml(不工作)

<ui:composition xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
                template="./../templateMenu.xhtml"
                xmlns:h="http://xmlns.jcp.org/jsf/html"
                xmlns:p="http://primefaces.org/ui"
                xmlns:c="http://xmlns.jcp.org/jsp/jstl/core">

  <ui:define name="left">
    <ui:include src="include/auMenu.xhtml"/>
  </ui:define>

  <ui:define name="content">
    <h1>Search 1</h1>

    <h:form id="form-busq-au">
      <p:panelGrid columns="2" styleClass="ui-noborder">
        <!--form fields -->

        <p:commandButton value="Search" icon="ui-icon-search" style="width: 100%;"
                         actionListener="#{searchView.setShowResults(true)}"
                         update=":form-res-au"/>
      </p:panelGrid>
    </h:form>

    <h:form id="form-res-au">
      <c:if test="#{searchView.showResults}">
        <h1>Search Results</h1>
      </c:if>
      <p:panelGrid id="panelgrid-res-au" columns="2" rendered="#{searchView.showResults}">
        <!-- other fields -->
      </p:panelGrid>
    </h:form>
  </ui:define>
</ui:composition>

正如您所看到的,它在测试和两个页面中的结构相同,但行为却不同。我不知道这是否是表面中的错误或什么。

调试代码我意识到在第二页中,<ui:composition xmlns:ui="http://xmlns.jcp.org/jsf/facelets" template="./../templateMenu.xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:p="http://primefaces.org/ui" xmlns:f="http://xmlns.jcp.org/jsf/core" xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"> <ui:define name="left"> <ui:include src="include/menu.xhtml"/> </ui:define> <ui:define name="content"> <h:form id="form-busq-mt"> <h1>Search 2</h1> <p:panelGrid columns="4" styleClass="ui-noborder"> <!-- form fields --> <p:commandButton value="Search" icon="ui-icon-search" style="width: 100%;" actionListener="#{searchView.setShowResults(true)}" update=":form-res-mt"/> </p:panelGrid> </h:form> <h:form id="form-res-mt"> <c:if test="#{searchView.showResults}"> <h1>Search Results</h1> </c:if> <p:panelGrid columns="2" rendered="#{searchView.showResults}"> <!-- Other fields --> </p:panelGrid> </h:form> </ui:define> </ui:composition> 方法永远不会被调用,不知道为什么。所以我尝试了以下解决方案:

尝试解决方案失败

认为这是setSearchResult(true) Managed Bean的问题,我在Controller中进行了更改:我使用属性和方法创建了一个抽象类,并为每个Web创建了一个SearchView扩展抽象类的页面。在代码中:

@ManagedBean

对于每个搜索页面:

public abstract class SearchView {
    private boolean showResults;

    public SearchView() {
        this.showResults = false;
        System.out.println("Constructor-showResults=" + this.showResults);
        System.out.println("Class: " + this.getClass().toString());
        System.out.println("ID: " + this.getClass().hashCode());
    }

    public boolean isShowResults() {
        return showResults;
    }

    public void setShowResults(boolean showResults) {
        this.showResults = showResults;
        System.out.println("Setter-showResults=" + this.showResults);
    }
}

但结果是相同的(在第二页中永远不会调用import java.io.Serializable; import javax.faces.bean.ManagedBean; import javax.faces.bean.ViewScoped; @ManagedBean @ViewScoped public class ConcreteXXXSearchView extends SearchView implements Serializable { private static final long serialVersionUID = -4717041016001640528L; } )。 setShowResult(true)中的println()方法是测试我实例化不同的对象(实际上,有不同的对象)。

我尝试了测试选项,但问题出在abstract class SearchView,因为<p:commandButton>无效。

综述

我在这里遇到两个问题:

  • 在测试中,我需要呈现一个actionListener,其中包含<h:form> UIComponentNamingContainer
  • 在项目中我需要知道为什么在失败页面中没有调用<p:panelGrid>

感谢任何帮助/指南。提前致谢

编辑:更多信息

TEST REAL PROBLEM 中,我使用浏览器检查器检查了 DOM setShowResults(true)属性对于两者都是正确的id<h:form id="form-res-mt">

1 个答案:

答案 0 :(得分:0)

您在非工作方法中使用了actionListener="#{searchView.setShowResults()}"

<p:commandButton value="Search" icon="ui-icon-search" style="width: 100%;"
                         actionListener="#{searchView.setShowResults()}"
                         update="form-res-mt"/>

但是,searchView.setShowResults()方法需要boolean argument,请将您的代码更改为:

 <p:commandButton value="Search" icon="ui-icon-search" style="width: 100%;"
                             actionListener="#{searchView.setShowResults(true)}"
                             update="form-res-mt"/>

另外,使用<ui:fragment rendered="yourCondition">代替<c:if test="condition"> ,因为如果组件条件返回false,则它不会附加到组件树。因此无法找到组件在UI树中。