JSF ui:ui重复包含:include包含在h:panelGroup中,带有条件渲染......一口气 [英] JSF ui:repeat included by ui:include wrapped in h:panelGroup with conditional rendering... A mouthfull

查看:256
本文介绍了JSF ui:ui重复包含:include包含在h:panelGroup中,带有条件渲染......一口气的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

原始问题如下,但我已经提出了一个更简单的例子来证明这个问题,并认为它应该在顶部。

Original question is below, but as I have come up with a more minimal example to demonstrate this problem, and figured it should go at the top.

无论如何,在检查父元素是否实际呈现之前,似乎处理了 ui:repeat 标记。要重新创建这个,这里是facelet(minimalTest.xhtml):

Anyway, it appears that ui:repeat tags are processed before checking to see if parent elements are actually rendered. To recreate this, here is the facelet (minimalTest.xhtml):

<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>Test JSF &lt;ui:repeat&gt; inside &lt;h:panelGroup rendered=&quot;false&quot;&gt;</title>
</h:head>
<h:body>
  <h:form>
    <h1>Testing</h1>
    <h:panelGroup rendered="false">
      <span>#{minimalTestBean.alsoThrowsException}</span>
      <ul>
        <ui:repeat value="#{minimalTestBean.throwsException}" var="item">
          <li>#{item}</li>
        </ui:repeat>
      </ul>
    </h:panelGroup>
  </h:form>
</h:body>
</html>

使用此bean(MinimalTestBean.java):

With using this bean (MinimalTestBean.java):

package com.lucastheisen.beans;


import java.io.Serializable;
import java.util.List;


import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;


@ManagedBean
@ViewScoped
public class MinimalTestBean implements Serializable {
    private static final long serialVersionUID = 9045030165653014015L;

    public String getAlsoThrowsException() {
        throw new RuntimeException( "rendered is false so this shouldnt get called either" );
    }

    public List<String> getThrowsException() {
        throw new RuntimeException( "rendered is false so this shouldnt get called" );
    }
}

从这个例子中你可以看到 h:panelGroup 包含 ui:repeat 静态设置为 rendered = false 我认为这意味着 h:panelGroup 中的EL表达式都不会被执行。 EL表达式只调用抛出RuntimeException的getter。但是, ui:repeat 实际上是为其列表调用getter,从而导致异常,即使它不应该首先呈现。如果您注释掉 ui:repeat 元素,则不会抛出任何异常(即使其他EL表达式仍保留在 h:panelGroup )正如我所料。

From this example you can see that the h:panelGroup that contains the ui:repeat is statically set to rendered=false which I would assume would mean that none of the EL expressions inside of that h:panelGroup would get executed. The EL expressions just call getters which throw a RuntimeException. However, the ui:repeat is actually calling the getter for its list thus causing the exception even though it should not be getting rendered in the first place. If you comment out the ui:repeat element, no exceptions get thrown (even though the other EL expression remains in the h:panelGroup) as I would expect.

在stackoverflow上阅读其他问题让我相信这可能与经常提到的chicken/egg 问题,但我不确定为什么,也不该怎么办。我想将PARTIAL_STATE_SAVING设置为false可能有所帮助,但是希望避免内存影响。

Reading other questions here on stackoverflow leads me to believe that is likely related to the oft-referred-to chicken/egg issue, but I am not sure exactly why, nor what to do about it. I imagine setting the PARTIAL_STATE_SAVING to false might help, but would like to avoid the memory implications.

----原始问题----

---- ORIGINAL QUESTION ----

基本上,我有一个页面有条件地使用< h:panelGroup rendered =#{modeXXX}> 包裹部分< ui:include src =pageXXX.xhtml/> (根据此答案)。问题是,如果其中一个pageXXX.xhtml里面有一个< ui:repeat> ,它似乎即使在包含< h:panelGroup> 已呈现= false 。这是一个问题,因为我的一些部分依赖于应该在它们之前访问的其他部分进行初始化。为什么包含的pageXXX.xhtml会被处理?

Basically, I have a page that conditionally renders sections using <h:panelGroup rendered="#{modeXXX}"> wrapped around <ui:include src="pageXXX.xhtml" /> (per this answer). The problem is that if one of the pageXXX.xhtml has a <ui:repeat> inside of it, it seems to get processed even when the containing <h:panelGroup> has rendered=false. This is a problem because some of my sections rely on having been initialized by other sections that should be visited before them. Why is the included pageXXX.xhtml getting processed?

这是一个痛苦的错误,很难归结为一个小例子,但这是我能做的最小的案例用于演示该问题的构建。首先是一个基页:

This is a painful bug and incredibly hard to boil down to a small example, but here is the most minimal case I could build that demonstrates the issue. First a base page:

<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>Test JSF &lt;ui:include&gt;</title>
</h:head>
<h:body>
  <h:form>
    <h1>#{testBean.title}</h1>
    <h:panelGroup rendered="#{testBean.modeOne}">
      <ui:include src="modeOne.xhtml" />
    </h:panelGroup>
    <h:panelGroup rendered="#{testBean.modeTwo}">
      <ui:include src="modeTwo.xhtml" />
    </h:panelGroup>
  </h:form>
</h:body>
</html>

如您所见,此页面将根据值有条件地包含modeOne页面或modeTwo页面在testBean bean中。然后你有modeOne(默认值):

As you can see this page will conditionally include either the modeOne page or the modeTwo page based upon the value in the testBean bean. Then you have modeOne (the default):

<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">
<ui:composition>
  <span>Okay, I&apos;m ready.  Take me to </span>
  <h:commandLink action="#{testBean.setModeTwo}">mode two.</h:commandLink>
</ui:composition>
</html>

在我的真实应用程序中,哪个页面可以设置modeTwo所需的内容。设置完成后,此页面上的操作将引导您进入modeTwo:

Which in my real world app would be a page that sets up things needed by modeTwo. Once set up, an action on this page will direct you to modeTwo:

<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">
  <ui:composition>
    <div>Here is your list:</div>
    <ui:repeat value="#{testBeanToo.list}" var="item">
      <div>#{item}</div>
    </ui:repeat>
  </ui:composition>
</html>

modeTwo页面基本上显示了ui中modeOne页面的详细信息:重复,因为实际信息是在一个集合中。主托管bean(TestBean):

The modeTwo page basically presents a details for the modeOne page in a ui:repeat as the actual information is in a collection. The main managed bean (TestBean):

package test.lucastheisen.beans;


import java.io.Serializable;


import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;


@ManagedBean
@ViewScoped
public class TestBean implements Serializable {
    private static final long serialVersionUID = 6542086191355916513L;
    private Mode mode;
    @ManagedProperty( value="#{testBeanToo}" )
    private TestBeanToo testBeanToo;

    public TestBean() {
        System.out.println( "constructing TestBean" );
        setModeOne();
    }

    public String getTitle() {
        System.out.println( "\ttb.getTitle()" );
        return mode.getTitle();
    }

    public boolean isModeOne() {
        return mode == Mode.One;
    }

    public boolean isModeTwo() {
        return mode == Mode.Two;
    }

    public void setModeOne() {
        this.mode = Mode.One;
    }

    public void setModeTwo() {
        testBeanToo.getReadyCauseHereICome();
        this.mode = Mode.Two;
    }

    public void setTestBeanToo( TestBeanToo testBeanToo ) {
        this.testBeanToo = testBeanToo;
    }

    private enum Mode {
        One("Mode One"),
        Two("Mode Two");

        private String title;

        private Mode( String title ) {
            this.title = title;
        }

        public String getTitle() {
            return title;
        }
    }
}

是所有的bean主要数据和TestBeanToo bean将用于详细信息:

Is the bean for all the main data, and the TestBeanToo bean would be for the details:

package test.lucastheisen.beans;


import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;


import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;


@ManagedBean
@ViewScoped
public class TestBeanToo implements Serializable {
    private static final long serialVersionUID = 6542086191355916513L;
    private ObjectWithList objectWithList = null;

    public TestBeanToo() {
        System.out.println( "constructing TestBeanToo" );
    }

    public String getTitle() {
        System.out.println( "\ttb2.getTitle()" );
        return "Test Too";
    }

    public List<String> getList() {
        System.out.println( "\ttb2.getList()" );
        return objectWithList.getList();
    }

    public void getReadyCauseHereICome() {
        System.out.println( "\ttb2.getList()" );
        objectWithList = new ObjectWithList();
    }

    public class ObjectWithList {
        private List<String> list;

        public ObjectWithList() {
            list = new ArrayList<String>();
            list.add( "List item 1" );
            list.add( "List item 2" );
        }

        public List<String> getList() {
            return list;
        }
    }
}


推荐答案

< ui:repeat> 不检查自身的呈现的属性(实际上没有)和视图要呈现时的父母。考虑使用 Tomahawk's < t:dataList>

<ui:repeat> does not check the rendered attribute of itself (it has actually none) and its parents when the view is to be rendered. Consider using Tomahawk's <t:dataList> instead.

这篇关于JSF ui:ui重复包含:include包含在h:panelGroup中,带有条件渲染......一口气的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆