如何在p:dataTable中展示当前行的详细信息并在保存后进行更新?

11

我有一个JSF 2应用程序,有两个页面,一个是列出学生的页面,另一个是显示给定学生详细信息的页面。在学生表的每一行中,列表页都有一个链接到详情页的链接,当单击时会在浏览器中打开一个新标签页来显示这些详细信息。

现在要求改变,不再在新标签页中显示详细信息,而是在列表页面中以模态对话框的形式显示。

我的想法是简单地将详细信息页面的内容嵌入到模态对话框中,这样列表页面就不会过大且难以维护。但是我有些疑虑。经过一些研究后,我将列表中每一行的链接更改为以下按钮:

<p:commandButton value="Details" type="button"
                 onclick="PF('dialog-details').show()">
</p:commandButton>

对话框的声明如下:

<p:dialog widgetVar="dialog-details" header="Details" modal="true" width="95%">
    <ui:include src="student_details.xhtml">
        <ui:param name="id" value="#{student.id}"/>
    </ui:include>
</p:dialog>

最后,详细页面被更改为像这样:

<ui:composition
    xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui" xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets">

    <f:metadata>
        <f:viewParam name="id" value="#{studentBean.id}" />
    </f:metadata>

    <h1 class="title ui-widget-header ui-corner-all">Details of #{studentBean.bean.name} / #{studentBean.bean.number}</h1>
</ui:composition>                       

当我点击按钮时,对话框会真正显示,内容是详细页面。我在对话框中看到以下内容:

Details of  / 

没有任何错误,但应该显示的数据却没有显示。在StudentBean.setId()方法中设置了断点(此方法将名为bean的属性加载到与传递的id相对应的Student实例中),但它从未被触发。

经过一段时间的思考,我明白了为什么它不起作用。传递到详细页面的参数是student.id,但student是用作<p:datatable/>中显示所有学生的var名称,因此student<p:datatable/>之外的<p:dialog/>中无效。

因此,我需要一种方法来使用给定行中相应学生的id显示对话框。理想情况下,在这里我想要一个ajax调用,这样只有在需要时才会加载详细信息。

有任何想法吗?


我将学习view标签,但在之前的详情页版本中没有使用它,在不同的浏览器选项卡中显示时仍然正常工作。 - AlexSC
@BalusC:谢谢你的提示,但它并没有帮助到我。我没有添加有关我的问题的一些细节:我的列表页面是一个组合,使用了一个模板,实际上有一个<f:view/>标记,因此对话框确实是<f:view/>的子元素,如该帖子所述。无论如何,我非常感谢你尝试帮助我! - AlexSC
1个回答

18

这里有一个启动示例:

<h:form id="master">
    <p:dataTable value="#{bean.entities}" var="entity">
        <p:column>#{entity.property1}</p:column>
        <p:column>#{entity.property2}</p:column>
        <p:column>#{entity.property3}</p:column>
        ...
        <p:column>
            <p:commandButton value="View" action="#{bean.setEntity(entity)}" 
                update=":detail" oncomplete="PF('detail').show()" />
        </p:column>
    </p:dataTable>
</h:form>

<p:dialog id="detail" widgetVar="detail">
    <h:form>
        <p:inputText value="#{bean.entity.property1}" />
        <p:inputText value="#{bean.entity.property2}" />
        <p:inputText value="#{bean.entity.property3}" />
        ...
        <p:button value="Close" onclick="PF('detail').hide(); return false" />
        <p:commandButton value="Save" action="#{bean.save}" 
            update=":master" oncomplete="if(!args.validationFailed) PF('detail').hide()" />
    </h:form>
</p:dialog>

使用这个在一个@ViewScoped的Bean中:

private List<Entity> entities; // +getter
private Entity entity; // +getter+setter

@EJB
private EntityService entityService;

@PostConstruct
public void load() {
    entities = entityService.list();
    entity = null;
}

public void save() {
    entityService.save(entity);
    load();
}

参见:


@Balus:太棒了!你的答案对我来说完美无缺,除了我必须将实体ID传递到将被包含的其他页面的部分。似乎参数根本不会传递到详细视图。 - AlexSC
@Alex: 我不理解这个功能要求。 请澄清一下。 您是否意味着您想在对话框中有一个指向另一个页面的<h:link>,并且您需要将#{entity.id}作为<f:param>传递? - BalusC
@Balus:基本上你理解的是对的,但要显示的细节非常广泛,而且我已经在另一个页面(另一个XHTML文件,记得当前实现在另一个浏览器选项卡中显示这些详细信息)中完成了它。因此,我想做的是在对话框内显示详细页面内容。 - AlexSC
1
然后,您可以将原始页面拆分为可通过<ui:include>包含在对话框中的内容,或者使用PrimeFaces对话框框架。 - Kukeltje

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接