DataTable中的Primefaces CommandButton传输随机对象

时间:2013-11-28 08:03:28

标签: jsf primefaces datatable commandbutton

我对PrimeFaces和JSF很新,我找不到类似情况的主题。 我检查过我没有嵌套表格。好像我遇到了一些奇怪的行为 - 至少我不知道它为什么会这样做;)

假设我有一个列表。 “模块”类有一个列表。我的目的是在一个表中显示数据,很好地按模块和它下面的行中的元素分组。 看起来像subtable是我的愿望成真,但我发现它只是报告问题,所以它是不可选择的。不幸的是,我需要知道在模块上运行“删除”或“编辑”等操作的选择。 我尝试在subtable facet中放置一个按钮,其中actionlistener在backing bean中设置当前对象,然后打开一个对话框以提供进一步的操作(在所选模块上)。我首先想到它有效,但后来注意到按下相同的按钮,一个随机的模块对象被转移到了支持bean。

<p:dataTable id="displayModules" var="displayModuleBean"
     value="#{displayModuleController.displayModuleBeans}"
     emptyMessage="Es existieren keine Module für diese Kampagne.">
     <p:row>
        <p:column headerText="Vermarkter" />
        <p:column headerText="Platzierung" />
        <p:column headerText="Umfeld" />
        <p:column headerText="Format(e)" />
        <p:column headerText="Startdatum" />
        <p:column headerText="Enddatum" />
        <p:column headerText="Abrechnungsart" />
     </p:row>

     <p:subTable id="displayModuleElements" var="displayModuleElement"
        value="#{displayModuleBean.moduleElements}"
        sortBy="#{displayModuleBean.module.name}" sortOrder="descending">
        <f:facet name="header" style="vertical-align: middle">
             #{displayModuleBean.module.name}

           <p:commandButton alt="Modul bearbeiten" icon="ui-icon-pencil"
              style="float:right"
              actionListener="#{displayModuleController.setSelectedDisplayModuleBean(displayModuleBean)}"
              oncomplete="displayModuleEditDialog.show();"
              update=":tabview:displayModulesDialogForm:editDisplayModules">
           </p:commandButton>
        </f:facet>

        <p:column headerText="Vermarkter">
           <h:outputText value="#{displayModuleElement.advertiserName}" />
        </p:column>
     </p:subTable>
  </p:dataTable>

Backing Bean(DisplayModuleController,SessionScoped):

public void setSelectedDisplayModuleBean(ModuleBean selectedDisplayModuleBean)
{
    this.selectedDisplayModuleBean = selectedDisplayModuleBean;
    this.setSelectedDisplayModuleName(this.selectedDisplayModuleBean != null ? this.selectedDisplayModuleBean.getModule().getName()
        : null);
    this.addFacesMessage(FacesMessage.SEVERITY_INFO, "Set selected ModuleBean: ",
        this.selectedDisplayModuleBean != null ? this.selectedDisplayModuleBean.getModule().getName() : "keins");
}

我甚至在每个标签上尝试过使用Accordion Panel和Datatables的解决方法,但我结束了同样奇怪的行为。我还尝试在每一行中添加一个按钮来传输所选元素本身(而不是父模块),但它的工作方式完全相同。

我到底错过了什么?如果有人可以帮助我以正确的方式前进,那会很棒;)

我正在使用: PrimeFaces 4.0, MyFaces 2.1.13, Apache Tomcat 7.0.42

LG, ANI

2 个答案:

答案 0 :(得分:1)

在表单提交期间解码操作方法时,将评估EL方法参数。在构建JSF组件树时,它们进行评估,或者生成HTML输出。

为了确保正在评估正确的EL方法参数值,您需要在此特定情况下确保在处理表单提交期间#{displayModuleController.displayModuleBeans}后面的模型完全相同就像在渲染(显示)表格时一样。

为了实现这一点,必须对支持bean进行视图作用,并且该模型的getter必须绝对没有任何业务逻辑。必须准备模型并填写一次性初始化/操作方法,例如@PostConstruct,以防您想要“在页面加载时”或在操作(监听器)方法中填充它,以防您遇到喜欢事先在“提交时”填充它。

否则,模型可能会关闭,因为您首先排序,然后通过unnecessarily在getter方法中执行DB调用,从数据库重新加载模型,就像许多初学者一样。


作为一种完全不同的替代方案,如果您无法确保模型的完整性,从而冒着在显示表单和处理表单提交之间不兼容更改的风险,那么您可以使用<f:param>传递静态参数。它将表示完全该值在播放表单期间(在呈现响应期间),而不是在处理表单提交期间。

E.g。

<p:commandButton ... actionListener="#{displayModuleController.setSelectedDisplayModuleBean}">
    <f:param name="id" value="#{displayModuleBean.id}" />
</p:commandButton>

您可以通过<f:viewParam name="id">@ManagedProperty("#{param.id}")externalContext.getRequestParameterMap().get("id")进行设置,然后根据ID DisplayModuleBean转换回具体的find()。另请参阅How can I pass selected row to commandLink inside dataTable?

答案 1 :(得分:0)

如果您正在处理实体您也可以将唯一ID作为参数传递给BackingBean,编写一个将ID作为参数的select方法,并将选定的Object设置为@WindowScoped BackingBean的实例。然后你可以这样访问你的实例:

 #{myBean.instance.propertyName}

通过这种方式,您可以确保使用正确的实例。