【问题标题】:JSF - how to add child to h:head or to h:body with managed beanJSF - 如何使用托管 bean 将子级添加到 h:head 或 h:body
【发布时间】:2017-04-03 15:14:55
【问题描述】:

我正在尝试测试我的托管 bean 以动态修改网页 (programmatically);大多数 jsf 示例展示了如何使用绑定来修改 ui,但是网页的其余部分呢?示例展示了如何到达通常位于h:body 块中的UIViewRoot,但是h:body 本身或h:head 呢?

所以我的问题是...有没有办法使用FacesContext 获取h:bodyh:head 作为父组件并使用托管bean 将子组件添加到它们,或者请告知如何获得相似 使用其他方式效果?

谢谢

【问题讨论】:

  • 您可以在 xhtml 中创建所有此类元素并使用托管 bean 中的变量显示/隐藏
  • @VikasSachdeva 我看不到任何示例;你能提供更多细节吗

标签: jsf jsf-2 managed-bean


【解决方案1】:

UIViewRoot<f:view> 标签表示。如果您没有在 JSF 页面中显式定义它,那么它会被隐式添加。

UIViewRoot 通常位于 h:body 块中

不,它不是在身体内部,而是默认围绕身体和头部。像这样:

<html xmlns="http://www.w3.org/1999/xhtml"  
    xmlns:h="http://java.sun.com/jsf/html"  
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"> 
    <f:view> <!-- No need to define. Added implicitly here in ComponentTree -->
        <h:head>
            <meta http-equiv="content-type" content="text/html;charset=UTF-8"/>
        </h:head> 
        <h:body>    
            <h:outputText value="#{hello.message}"/>            
       </h:body>
   </f:view>
</html> 

因此,如果您使用FacesContext.getCurrentInstance().getViewRoot() 获取 UIViewRoot 并请求其子级 (.getChildren()),您将获得一个包含 4 个元素的列表:

  1. UIInstructions: 渲染&lt;html&gt;opening 标签
  2. UIOutput:这是&lt;h:head&gt;。再次请求getChildren 以获得UIOutput&lt;meta&gt; 标签
  3. HtmlBody:这显然是h:body。要求getChildren 获取&lt;h:outputText&gt;
  4. UIInstructions:呈现 &lt;/html&gt; 结束标签

使用托管 bean 将孩子添加到他们身上

是的,通常您可以使用 ManagedBeans 来操作 UIComponentTree(例如,添加项目,然后重新加载页面以显示它)。但是,请考虑JSF lifecycle 和处理顺序(例如,您不能在渲染阶段将子元素作为第一个元素添加到主体,因为项目已经被处理)。 将新元素添加到正文的示例:

List<UIComponent> viewRootChildren = FacesContext.getCurrentInstance().getViewRoot().getChildren();
for(UIComponent child : viewRootChildren){
    if( child instanceof HtmlBody ){
        HtmlOutputText newText = new HtmlOutputText();
        newText.setValue("added dynamically");
        child.add(newText);
    }
}

【讨论】:

  • 这很有趣 :) 所以 UIInstructions 是 UIOutput 和 HtmlBody 的父级?
  • 不,即使 &lt;html&gt;&lt;f:view&gt; 的父级,&lt;f:view&gt;&lt;h:head&gt;&lt;h:body&gt; 的父级,但对于 Java 端的 UIComponentTree 而言并非如此。相反,所有这 4 个元素都位于同一层次结构级别(UIViewRoot 的子级)。然后,您可以在这 4 个元素中的任何一个上再次调用 getChildren,其中 UIInstructions 没有更多子元素(但仅呈现 html)。 UIOutput 和 HtmlBody 确实有更多的孩子,您可以通过 Java 操作它们。
  • 我建议暂时忽略&lt;html&gt;UIInstructions。这与包含 html-root-element 的其他标签不同。您的问题是关于如何获得h:headh:body(第2 和第3 个元素),这可以按照所述完成。也许只是尝试在 ManagedBean 中的任何位置调用FacesContext.getCurrentInstance().getViewRoot().getChildren(),设置断点并调试/检查以查看 UIComponentTree。
  • 更新了关于如何将元素添加到正文的答案。
  • 我知道了,但是 JSF 生命周期呢?我的意思是我可以在 encodeBegin(...) 中获取 HtmlBody 或获取哪个事件?
【解决方案2】:

您可以使用 rendered 属性显示/隐藏您的 JSF 组件。

下面是一个示例 -

<h:outputText value="Result = #{calculator.result}" rendered="#{calculator.result != null}"/>

这里,只有当 calculator.result 不是 null 时,此元素才会显示在 UI 中,其中 calculator 是您的 managedBean 的名称,result 是该 bean 中的一个变量。您可以在预渲染事件或 AJAX 调用或其他事件中更改此变量的值。

对于多个元素,您可以使用 &lt;h:panelGroup&gt;rendered 属性。

【讨论】:

  • 请在 StackOverflow 上找到这个的“重复”...几十个,并将问题标记为其中一个的重复。
  • 不,我的意思是如何使用 FacesContext 以编程方式创建组件:S 不是标签方式。请参阅我在问题中提供的链接
  • 我认为这可能不可行。但是,您可以使用渲染属性实现相同的效果。
  • 渲染属性即将在视图中定位为其子级或类似属性;但是h:head itseld 或h:body 本身呢?我不知道如何找到他们,所以请给我一个提示如何将孩子添加到头部或身体;如果您知道最佳方式,请分享...
猜你喜欢
  • 2016-07-09
  • 1970-01-01
  • 2011-03-25
  • 2011-10-29
  • 2014-07-01
  • 2023-03-05
  • 2013-08-20
  • 1970-01-01
  • 2023-03-27
相关资源
最近更新 更多