【问题标题】:Initialize Managed Bean from view从视图初始化托管 Bean
【发布时间】:2011-02-09 16:39:49
【问题描述】:

我在处理我应该在我的应用程序上使用什么 Scope 时遇到了很大的困难。

我正在使用 Primefaces,并使用 a 作为我的初始视图布局。在布局之外,我有许多不同的托管 bean 使用的对话框。

在我的布局中,我有一个页眉、页脚和左侧的导航,然后是中心的当前视图。所以我的看法如下:

<h:body id=body">
   <p:layoutUnit id=head" position="top">
         <ui:insert name="header">
   </p:layoutUnit>
   <p:layoutUnit id=head" position="bottom">
         <ui:insert name="footer">
   </p:layoutUnit>
   <p:layoutUnit id=head" position="left">
         <ui:insert name="menu">
   </p:layoutUnit>
   <p:layoutUnit id=head" position="right">
         <ui:insert name="main">
   </p:layoutUnit>

   <p:dialog widgetVar="addAddressDialog" header="Add New Address">
       <h:form id="insertAddress">
            <h:inputText id="insert_address" label="Address" />
       </h:form>
   </p:dialog>

   <p:dialog widgetVar="updateAddressDialog" header="Add New Address">
       <h:form id="updateAddress">
            <h:inputText id="update_address" value=#{addressBean.selectedAddress.address" />
       </h:form>
   </p:dialog>

我遇到的问题是,当我的应用程序第一次加载 addressBean 的 @PostConstruct 时,因为正在加载视图而被调用。在@PostConstruct 中,我初始化了与名为contactId 的特定ID 关联的地址列表。此时虽然contactId 还没有被实例化。一旦用户与“主”视图交互,就会发生这种情况。

addressBean 的我的范围当前是@ViewScope,它可以查找但仅在第一次设置contactId 时才起作用。之后,即使contactId 发生更改,它也会继续保留填充的信息,因为@PostConstruct 再也不会被调用,并且视图似乎永远不会超出范围。

我已经尝试过@RequestScope,这实际上非常有效。但是在“主”视图内的数据表中显示地址时遇到了问题。我的数据表底部有一个名为 insertAddressDialog.show() 的按钮。它第一次打开,我可以插入数据,但是 1. 数据表的视图永远不会显示我插入的新记录,因为我猜那个视图已经丢失了。 2.数据表上的按钮不再活动或活动,因此在用户第一次插入记录后对话框不会打开。

这似乎应该是一件容易的事,但我的应用程序有许多嵌套视图,这导致了问题。任何有关如何处理此类事情的见解都会有所帮助。

【问题讨论】:

    标签: jsf-2 primefaces


    【解决方案1】:

    这听起来不像是 PrimeFaces 问题。

    只要您不离开与其关联的页面(视图),ViewScoped bean 就会保持在范围内。每次您与之交互时,RequestScoped bean 都会重新实例化。如果您尝试在一次交互中将变量存储到 RequestScoped bean 中,然后在第二次交互中使用这些变量更新数据库,第二次交互将重新实例化 bean,并且您的变量将消失(好吧,变量仍然存在 - 它的值消失了)。

    您是否有令人信服的理由使用@PostConstruct 来初始化地址?听起来您有一个主页,用户开始与程序交互,用户从该主页输入(或程序以其他方式检索)用户的contactId。此contactId 变量用于填充显示与该用户的contactId 关联的所有地址的数据表。听起来错误出在您的 bean 逻辑中。

    您需要先获取contactId,然后使用它来填充数据表。我不知道您的程序/用户如何与 bean 交互以提供contactId。如果contactId是用户输入的,那么不要在@PostConstruct中初始化地址列表,因为它总是会在输入contactId之前被初始化。如果程序自动从 user 类型的变量中获取 contactId(它知道是因为用户登录并且程序从数据库中创建/检索了用户的 contactId),那么您应该能够将该代码包含在@PostConstruct - 在数据表初始化之前。

    或者,不使用@PostConstruct,只需在网页中您的页面(视图)引用任何变量的位置包含一个方法调用。您可以将方法调用直接放在页面上:

    #{myBean.myMethod} 其他代码在这里...

    应该在调用方法之前调用和构造 bean,并且您的用户的 contactId 应该可用于 bean 的数据操作。 (我对最后一点做出假设,因为我们看不到您的 bean 逻辑。)

    【讨论】:

    • “你可以把方法调用直接放在页面上:#{myBean.myMethod} 这里的其他代码......”这是我没有想到的一个想法,但这对我不起作用.您对我的程序如何工作的假设是正确的。我只需要一种在加载视图之前或在视图顶部实例化 bean 的方法,就像您建议的那样。
    • 我可以将 login 放在我的数据表列表的 getter 中,例如 if(address == null) { myDao.getAddresses();返回地址 } else { 返回地址} 但我认为他认为任何逻辑都不应该进入 setter 和 getter。
    • 好的,你的 bean 在视图加载之前被实例化了。这就是给您带来问题的原因,bean 被实例化(构造),然后立即调用 @PostConstruct。在将contactId 传递给您的bean 之后,您需要初始化您的数据表。您也可以在@PostConstruct 中设置您的contactId,特别是因为它在实例化您的bean 之前已经存在,然后在@PostConstruct 中初始化您的数据表。您的问题只是逻辑流程。
    猜你喜欢
    • 2014-09-28
    • 1970-01-01
    • 1970-01-01
    • 2011-09-24
    • 2013-01-06
    • 1970-01-01
    • 2014-06-12
    • 2013-06-16
    • 1970-01-01
    相关资源
    最近更新 更多