On a recent training course, we will build the following proof. We created a single view with two tables, a wizard (department) and a table of parts (employees). The view was supported by two beans controllers that exchange cdi data. Resonance: BackgroundConcept has been deployed to a jee6 container (glassfish 3.1.1).
The idea is that whenever you click on the departments line, ajax-Listener fires a cdi event, which updates the controller parts and in turn updates the details table. This template can be expanded to several detailed tables or several levels of detail-part-part.
To edit your suggestions, I suggest opening an editor dialog, for example, adding an editor button to each row of your tables. To add new data, use add-Actions in the table footer and open the editor dialog box with the new object. On "ok" in your Dialog editor, you again fire the cdi event with a new entity to update depending on the detailed tables. To save your work, use one "commit" -Button, which saves the master-Entity. In the training, we used jpa with the corresponding specific objects, esp, using the orphanRemoval = true attribute in the @OneToMany relationship.
View (scott.xhtml):
<p:panel id="deptPanel" header="Departements"> <p:dataTable id="deptTable" var="dept" value="#{deptUiController.departements}" selectionMode="single" rowKey="#{dept.id}"> <p:ajax event="rowSelect" listener="#{deptUiController.onRowSelect}" update="@form"/> <p:column headerText="Name"> <h:outputText id="name" value="#{dept.dname}"/> </p:column> <p:column headerText="Location"> <h:outputText id="loc" value="#{dept.loc}"/> </p:column> <p:column headerText="# of Emps"> <h:outputText id="size" value="#{dept.emps.size()}"/> </p:column> </p:dataTable> </p:panel> <p:panel id="empPanel" header="Employees in departement #{deptUiController.currentDept.dname}"> <p:dataTable id="empTable" var="emp" value="#{empUiController.employees}"> <p:column headerText="Name"> <h:outputText id="name" value="#{emp.ename}"/> </p:column> <p:column headerText="Job"> <h:outputText id="job" value="#{emp.job}"/> </p:column> <p:column headerText="Hiredate"> <h:outputFormat id="hiredate" value="{0,date,dd.MM.yyyy}"> <f:param value="#{emp.hiredate}"/> </h:outputFormat> </p:column> </p:dataTable> </p:panel>
Master controller:
@Named @SessionScoped public class DeptUiController implements Serializable { private boolean initialized = false; @EJB private ScottCRUD crudEJB; private List<Departement> departements; private Departement currentDept; public void populateData() { if ( !initialized ) { departements = crudEJB.findAllDepartements(); currentDept = departements.isEmpty() ? null : departements.get(0); initialized = true; fireDeptChange(); } } @Inject private Event<Departement> deptChangeEvt; private void fireDeptChange() { deptChangeEvt.fire( currentDept ); } public void onRowSelect(SelectEvent event) { currentDept = (Departement) event.getObject(); fireDeptChange(); } ... getter, setter, more actions... }
Controller part
@Named @SessionScoped public class EmpUiController implements Serializable { private List<Employee> employees; private Employee currentEmp; private void populateData(Departement master) { if ( master==null ) { employees = Collections.emptyList(); } else { employees = master.getEmps(); } currentEmp = employees.isEmpty() ? null : employees.get(0); } public void observeDeptChanged( @Observes Departement master ) { populateData( master ); } ... getter, setter, more actions... }