【问题标题】:How to use component binding in JSF right ? (request-scoped component in session scoped bean)如何在 JSF 中正确使用组件绑定? (会话范围 bean 中的请求范围组件)
【发布时间】:2013-09-11 03:40:36
【问题描述】:

Mojara 2.1.21

我已经根据 cmets 更新了我的问题。我有两种情况,组件绑定到服务器会话 bean。 (其他信息链接:Binding attribute causes duplicate component ID found in the viewhttps://stackoverflow.com/a/12512672/2692917

版本 1:

single.xhtml:

 <h:outputText value=... binding="#{mysessionbean.out}" />

java:

 @SessionScoped @Named public class Mysessionbean {
    UIOutput out;
    //getter and setter ....
 }

版本 2:

模板.xhtml:

 <h:outputText value=... binding="#{mysessionbean.out}"

view1.xhtml:

 <ui:composition template="template.xhtml" />

view2.xhtml:

 <ui:composition template="template.xhtml" />

java:

 @SessionScoped @Named public class Mysessionbean {
    UIOutput out;
    //getter and setter ....
 }

版本 1 没问题。 (至少到目前为止我还没有遇到任何错误)。但是在版本 2 中,如果我从一个页面导航到另一个页面,则会发生重复的 id 错误。为什么会这样? 将(请求范围的)组件(在版本 1 中)与会话范围的绑定一起使用是否安全? 还有其他用例需要考虑吗?

编辑: 功能要求1:

我想在视图中使用 Primefaces 数据表。我需要这个数据表中的一些信息。 (如选中的行或行索引)。所以绑定数据表可以帮助我检索这些信息。

功能要求2:

复合组件中的组件绑定。它们将绑定到会话范围的 bean。 (而且主要用在一个页面上,但是如果我在另一个页面上使用呢?

要求 3

“版本2”中的情况。带有 primefaces 菜单和会话范围绑定的模板。为此,我使用了 EL-Binding。

【问题讨论】:

  • 这绝对是不对的,不。组件实例本质上是请求范围的。另请参阅:stackoverflow.com/questions/2101755。在发布答案之前,请详细说明您认为这是正确解决方案的具体功能要求。然后我可以说出正确的方法。
  • @BalusC 感谢您的评论!我已经更新了我的问题。
  • 您还没有详细说明功能需求。
  • @BalusC 我已经更新了我的问题
  • 2 和 3 不清楚。缺少功能需求。

标签: jsf jsf-2 scope


【解决方案1】:

在 JSF 2.x 中,除非您想以编程方式操作组件(这本身也很可疑),否则没有明智的现实世界用例将组件绑定到支持 bean。如果它们进一步没有在 backing bean 本身中使用,或者仅仅是它们的属性被扁平化,那么肯定不会。


关于获取数据表当前行的功能需求,这里列出了很多更好的方法,How can I pass selected row to commandLink inside dataTable?,例如如果你的环境支持EL 2.2:

<h:dataTable value="#{bean.items}" var="item">
    <h:column>
        <h:commandLink value="Foo" action="#{bean.foo(item)}" />

最后两个要求完全不清楚。至少,如果你正在做类似的事情:

<x:someComponent binding="#{bean.someComponent}" />

在 bean 中

someComponent.setSomeAttribute(someAttribute);
someComponent.setOtherAttribute(otherAttribute);

那么你应该这样做

<x:someComponent someAttribute="#{bean.someAttribute}" otherAttribute="#{bean.otherAttribute}" />

或者,如果您打算像这样在视图中的其他位置使用该组件

<h:inputText ... required="#{not empty param[bean.save.clientId]}" />
...
<h:commandButton binding="#{bean.save}" ... />

并且该实例在 bean 中进一步没有被使用,然后完全摆脱不必要的属性:

<h:inputText ... required="#{not empty param[save.clientId]}" />
...
<h:commandButton binding="#{save}" ... />

如果由于某种不清楚的原因真的真的没有办法,那么将会话范围 bean 的所有请求范围属性拆分为一个单独的请求范围 bean,然后您将其绑定到表单操作。会话范围的一个可以作为请求范围的一个@ManagedProperty 注入。


另见:

【讨论】:

  • 很好的抽象解释!对于您的最后一个建议,我正在使用 CDI,那么我可以在会话范围内注入请求范围的包装类吗?因为可能我需要会话范围 bean 中的组件,因为相反。
  • 是的,反过来也可以。
【解决方案2】:

我们遇到了类似的问题,我只想分享我们的解决方案:

问题: 在一个视图中,有一个(扩展的大部分定制的)数据表。

<x:dataTable binding="#{bean.someSomeDataTable}" />

在导航到另一个页面并返回后,我们希望数据表具有完全相同的状态。以前我们通过将数据表绑定到支持 bean 来解决这个问题。这适用于 JSP。使用 Facelets,我们无法做到这一点(重复 ID 错误)。所以我们使用了绑定,但只是保存/恢复了数据表组件的状态。

public HtmlDataTable getSomeDataTable()
{
 HtmlDataTable htmlDataTable = new HtmlDataTable();
 if (tableState != null)
   htmlDataTable.restoreState(FacesContext.getCurrentInstance(), tableState);
 return htmlDataTable;
}

public void setSomeDataTable(HtmlDataTable table)
{
  tableState = table.saveState(FacesContext.getCurrentInstance());
}

【讨论】:

  • 感谢您分享您的解决方案!
猜你喜欢
  • 2011-09-02
  • 2014-12-02
  • 1970-01-01
  • 2012-08-01
  • 2016-01-02
  • 2011-01-11
  • 2011-11-11
  • 2012-05-26
  • 2013-08-26
相关资源
最近更新 更多