【问题标题】:How to retrieve value of a ui:param in the backing bean如何在支持 bean 中检索 ui:param 的值
【发布时间】:2013-01-05 18:14:23
【问题描述】:

我正在将参数p1 传递到另一个页面page.xhtml

<ui:include src="page.xhtml">
    <ui:param name="p1" value="#{someObject}"/>
</ui:include>

这是否可以在 page.xhtml 的支持 bean 的 @PostConstruct 方法内评估 #{p1}?使用以下代码,#{p1} 无法解析:

FacesContext currentInstance = FacesContext.getCurrentInstance();
currentInstance.getApplication().evaluateExpressionGet(currentInstance, "#{p1}", String.class);

我为什么需要这个?

我使用 xhtml 文件(比如 component.xhtml)作为自定义 UI 组件。这个文件有一个支持 bean,我应该从中获取组件数据。由于我在我的主 JSF 页面中包含此 xhtml 文件两次或更多次,因此我想将不同的对象传递给每个 component.xhtml,以便我的组件每次都使用我的自定义数据。

【问题讨论】:

  • 这段代码位于哪个backing bean方法中?
  • 更新了我的问题:@PostConstruct 方法。
  • 这可能是个问题。 @PostConstruct 方法可以在页面构建之前执行。尝试为preRenderView定义f:event,看看是否解决。
  • 听起来很奇怪! preRenderView/preRenderComponent 监听器未在包含页面中调用。
  • 似乎preRenderView 在包含的页面中不起作用。见:stackoverflow.com/questions/12543405/…

标签: jsf-2 parameters el


【解决方案1】:

@PostConstruct 方法中没有该参数;您可以使用 preRenderComponent 事件来初始化支持 bean 中的参数;只要放在被包含页面的ui:composition之后,它就会在被包含页面本身的渲染之前执行。

遵循将 p1 参数传递给 page.xhtml 模板的 OP 示例

主页:

<ui:include src="page.xhtml">
    <ui:param name="p1" value="#{someObject}"/>
</ui:include>

page.xhtml:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    ...>

<ui:composition>
    <f:event listener="#{backingBean.init(p1)}" type="preRenderComponent"/>
        ...

</ui:composition>

</html>

BackingBean.java:

@ViewScoped
 public class BackingBean{

     private Object p1;
     public void init(Object value){        
     this.p1=p1;
    }

    ...
 }

在渲染 ui:composition 标签之前触发事件,也就是在渲染 page.xhtml 之前

【讨论】:

    【解决方案2】:

    这对我有用:

    <ui:include src="page.xhtml">
         <ui:param name="p1" value="#{someObject}"/>
    </ui:include>
    

    page.xhtml:

    <c:set var="data" value="#{p1}" scope="request"/>
    

    你的豆子:

    @ViewScoped
    public class ManagedBean{
    
         private Object someObject;
    
         public Object getSomeObject(){
             if(someObject== null){
                HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
                someObject= request.getAttribute("data");
              }
              return someObject;
         }
    
         public void setSomeObject(Object someObject){
              this.someObject = someObject;
         }}
    

    【讨论】:

      【解决方案3】:

      在 Mojarra 中,您可以将其作为FaceletContext 的属性来获取。您可以在托管 bean 的 @PostConstruct 中获取它,该 bean 保证在包含的页面中首次被引用/构造(因此不在父页面中之前 &lt;ui:param&gt; 是在组件树中声明)。

      FaceletContext faceletContext = (FaceletContext) FacesContext.getCurrentInstance().getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
      Object p1 = faceletContext.getAttribute("p1");
      

      在 MyFaces 中,整个 FaceletContext 在托管 bean 中不可用,因为它在视图构建时间结束时被丢弃,然后此构造将不起作用。要独立于 JSF 实现,您可能需要考虑改为通过 &lt;c:set scope="request"&gt; 设置它。然后它可以作为请求属性使用。

      对于具体的功能要求,考虑创建一个带有支持组件的复合组件。有关一些示例,请参阅 our composite component wiki page 和有关 using multiple input components in a composite component 的博客。另见When to use <ui:include>, tag files, composite components and/or custom components?

      【讨论】:

      • "一个保证在被包含页面中第一次被引用/构造的托管bean" 如果页面与父页面同时加载,应该还是可以的因为它从未在父母中使用过,对吗?还是我们需要延迟加载以确保这一点?
      • 如果不能保证就拆分成一个新的bean。您可以在必要时轻松注入“父”bean。
      • 好吧,我有一个专门用于复合材料的 bean,但即使我延迟加载复合材料(使用 primefaces 覆盖),我的参数也不会添加到上下文中。
      • 复合?那不是“包含页面”。请改用支持组件。另请参阅答案底部的链接。然后你可以简单地做类似stackoverflow.com/q/21525669
      • 对不起,我的意思是合成而不是合成。 (不确定有什么区别,因为我从未使用过复合材料)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多