Search code examples
jsfjsf-2richfacesprimefacesopenfaces

Use of JSF view parameter through datatables? Possible?


Environment: JSF 2.0 / JPA (provided by EclipseLink) / Glassfish 3.1 / java-EE-5 /

  • A small JSF (No Spring, no EJB, no CDI) web application consists mainly on displaying datatables for entities, but the purpose is to display the list of an entity iems for a given Writer:

  • A datatable (<h:datatable/>) displays the list of Writers.

  • A datatable (<h:datatable/>) displays the list of Books written by Writers. (1--*)
  • A datatable (<h:datatable/>) displays the list of Evaluations given to Writers. (1--*)
  • A datatable (<h:datatable/>) displays the list of Topics treated by Writers. (1--*).

This is how I am seeing things:

Since all the datatables have a column with the Writer ID (primary key of Writer). How can I achieve telling the current user session to hold a parameter (Writer ID), when the user selects a given writer (preferably from the Writer datatable) and use it to display only the records related to that selected writer row.

The same way, when a user is done with the selected writer, he/she can reset the session to hold another writer ID and explore happily with the new selected writer child items.

In other words, using <h:datatables />, and <f:param /> (or something similar), how can I list Book, Evaluation and Topic items for a selected writer persistently.

E.G: Persistently for me means = When the user selects a writer from the datatable, and navigates to /book/List.xhtml page, the book datatable must list only the book items that the selected writer has. And if the user navigates to somewhere else, he can see only what's related to the same writer.

One idea is to use OpenFaces datatable filters, but it is too cruel for the end user to filter the table each time he/she navigates to a page. He has to do it only once. (An exciting solution is to add an OpenFaces filter (<o:inputTextFilter />) for each datatable (<o:datatable > in that case) and then all the filters for all tables get automatically the writer ID held as parameter by the user session during the JSF cycle. But is that really feasible :( ?

Sorry for the redundancy. Hope someone could help with hints, ideas, solutions or better alternative. regards.


Solution

  • Assuming that you're indeed running Java EE 6 and not Java EE 5, you could just pass the currently selected writer as method argument to the bean in a commandlink/button in a datatable and let the other tables depend on that.

    Given the following Writer entity:

    public class Writer {
    
        private String name;
        private List<Book> books;
        private List<Evaluation> evaluations;
        private List<Topic> topics;
    
        // ...
    }
    

    and the following managed bean:

    @ManagedBean
    @ViewScoped // request or session are also okay.
    public class Bean {
    
        private List<Writer> writers; // +getter
        private Writer writer; // +getter +setter
    
        // ...
    }
    

    then you can setup your datatables as follows (in a single view):

    <h:form>
        <h:dataTable value="#{bean.writers}" var="writer">
            <h:column>#{writer.name}</h:column>
            <h:column>
                <h:commandButton value="View" action="#{bean.setWriter(writer)}">
                    <f:ajax render=":details" />
                </h:commandButton>
            </h:column>
        </h:dataTable>
    </h:form>
    <h:panelGroup id="details">
        <ui:fragment rendered="#{not empty bean.writer}">
            <h:dataTable value="#{bean.writer.books}" var="book">
                <h:column>#{book.name}</h:column>
                ...
            </h:dataTable>
            <h:dataTable value="#{bean.writer.evaluations}" var="evaluation">
                <h:column>#{evaluation.name}</h:column>
                ...
            </h:dataTable>
            <h:dataTable value="#{bean.writer.topics}" var="topic">
                <h:column>#{topic.name}</h:column>
                ...
            </h:dataTable>
        </ui:fragment>
    </h:panelGroup>