How to show details of current row from p:dataTable in a p:dialog and update after save
Asked Answered
C

1

11

I have a JSF 2 application that has two pages, one to list students and one to show details of a given student. The listing page has a link to the details page in each row of the students table, that opens a new tab in browser to show those details, when clicked.

Now the requirements changed to no more show details in a new tab, but in a modal dialog in the listing page.

My idea is to simply embed the details page content in the modal dialog so the listing page will not get too big and hard to maintain. Here start my doubts. After some research I changed the link in each row of the listing to the following button:

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

The dialog is declared as follows:

<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>

Finally, the details page was changed to be something like this:

<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>                       

When I click the button, the dialog really shows and the content is the details page. I see the following content in the dialog:

Details of  / 

No errors at all, but the data that should be shown, isn't. A breakpoint was set in StudentBean.setId() (this method loads a property named bean with the Student instance corresponding to the passed id) but it is never hit.

After some time thinking about it, I came to understand why it does not work. The parameter passed to the details page is student.id, but student is the name used as the var in the <p:datatable/> that show all the students, so student is not valid in <p:dialog/> which is outside the <p:datatable/>.

So, what I need is a way to show the dialog using the id of the corresponding student in a given row. Ideally, I would like an ajax call here, so the details would loaded only when neded.

Any ideas?

Candycandyce answered 30/1, 2015 at 12:43 Comment(2)
I'll study the view tag, but I was not using it in the previous version of the details page and it was working properly when showed in a different browser tab.Candycandyce
@BalusC: Thanks for your tip, but it din't help me. I didn't add some details about my problem: my listing page is a composition and uses a template that actually has a <f:view/> tag, so the dialog indeed is a child of a <f:view/> as the post informed. Anyways, I'm very grateful for your attempt to help me!Candycandyce
P
19

The button should be an ajax button which sets the currently iterated entity in the bean, and then updates the dialog's content, and finally shows it. The dialog should just reference that entity in the bean and update the list and table on save. It's very important that dialog is placed outside the main form and that it has its own form.

Here's a kickoff example:

<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>

With this inside a @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();
}

See also:

Paralyze answered 30/1, 2015 at 14:0 Comment(4)
@Balus: Great! Your answer worked perfectly for me, except for the part that I have to pass the entity id to the other page that will be included. It seems that the parameter simply doesn't go to the details view.Candycandyce
@Alex: I'm not understanding the functional requirement. Please clarify. Do you mean that you want to have a <h:link> in the dialog pointing to another page and that you need to pass #{entity.id} as <f:param>?Paralyze
@Balus: it's basically what you understood, but the details to be shown are very extensive and I already have it done in a different page (another XHTML file, remember the current implementation show those details in another browser tab). So, what I would like to do is to show the details page content inside the dialog.Candycandyce
Then either split the original page in something you can include in the dialog via <ui:include> or use the primefaces dialog framework.Satiate

© 2022 - 2024 — McMap. All rights reserved.