In any case, popup modal panels tend to disrupt the flow of the page. What would be good is to be able to edit both Master and Detail entities on a single page. The following example produces a screen that looks like:

So to the code. This uses exactly the same backing bean as the other examples - a conversation-scoped edit manager - with no changes at all. Code for that is available here.
The page.xml file looks like:
<?xml version="1.0" encoding="UTF-8"?>
<page xmlns="http://jboss.com/products/seam/pages"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.com/products/seam/pages http://jboss.com/products/seam/pages-2.1.xsd"
no-conversation-view-id="/MasterList.xhtml"
login-required="true">
<begin-conversation join="true" flush-mode="MANUAL"/>
<action execute="#{masterEditor.wire}" on-postback="false"/>
<param name="masterFrom"/>
<param name="masterId" value="#{masterEditor.masterId}"/>
<navigation from-action="#{masterEditor.persist}">
<rule>
<end-conversation/>
<redirect view-id="/OnePageEdit.xhtml"/>
</rule>
</navigation>
<navigation from-action="#{masterEditor.update}">
<rule>
<end-conversation/>
<redirect view-id="/OnePageEdit.xhtml"/>
</rule>
</navigation>
<navigation from-action="#{masterEditor.remove}">
<rule>
<end-conversation/>
<redirect view-id="/MasterList.xhtml"/>
</rule>
</navigation>
</page>
The XHTML file is:
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:s="http://jboss.com/products/seam/taglib"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:a="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich" template="layout/template.xhtml">
<ui:define name="body">
<h:form id="master" styleClass="edit">
<rich:panel>
<f:facet name="header">Master Details</f:facet>
<s:decorate id="masterDescriptionField" template="layout/edit.xhtml">
<ui:define name="label">Master description</ui:define>
<h:inputText id="masterDescription" size="100" maxlength="100"
value="#{masterEditor.instance.masterDescription}">
<a:support event="onblur" reRender="masterDescriptionField"
bypassUpdates="true" ajaxSingle="true" />
</h:inputText>
</s:decorate>
<div style="clear: both">
<span class="required">*</span>
required fields</div>
</rich:panel>
<a:region>
<h:panelGrid id="detailEdit" columns="2" columnClasses="detailList,detailDetail" width="100%">
<h:panelGroup>
<rich:dataTable id="detailListTable" var="_detail" value="#{detailListFromMaster}"
width="200px" styleClass="scriptPagesList"
onRowMouseOver="this.style.backgroundColor='#EAEAEA';this.style.cursor='pointer'"
onRowMouseOut="this.style.backgroundColor='#{a4jSkin.tableBackgroundColor}'">
<h:column>
<f:facet name="header">
<ui:include src="layout/sort.xhtml">
<ui:param name="propertyLabel" value="Id" />
</ui:include>
</f:facet>
<h:outputText value="#{_detail.id}" />
</h:column>
<a:support event="onRowClick"
reRender="detailEditDetail"
action="#{masterEditor.select()}">
</a:support>
</rich:dataTable>
<div style="clear: both" />
<div class="actionButtons">
<a:commandButton id="NewDetailButton"
value="New Detail"
action="#{masterEditor.createNewDetail}"
reRender="detailEdit"
styleClass="buttonNoBorders">
<s:conversationId />
</a:commandButton>
<a:commandButton id="DeleteDetailButton"
value="Delete Detail"
action="#{masterEditor.removeDetail(currentDetail)}"
enabled="#{currentlySelectedDetail!=null}"
reRender="detailEdit"
styleClass="buttonNoBorders">
<s:conversationId />
</a:commandButton>
</div>
</h:panelGroup>
<h:panelGroup>
<rich:panel id="detailEditDetail" styleClass="panelNoBorder">
<f:facet name="header">Detail Details</f:facet>
<s:div rendered="#{currentlySelectedDetail!=null}">
<s:decorate id="detailDescriptionField" template="layout/edit.xhtml">
<ui:define name="label">Detail description</ui:define>
<h:inputText id="detailDescription"
required="true"
size="100"
maxlength="100"
value="#{currentlySelectedDetail.detailDescription}">
<a:support event="onblur" reRender="detailDescriptionField" bypassUpdates="true" ajaxSingle="true" />
</h:inputText>
</s:decorate>
</s:div>
</rich:panel>
</h:panelGroup>
</h:panelGrid>
</a:region>
<rich:panel styleClass="panelTopBorderOnly"
bodyClass="panelTopBorderOnlyBodyClass">
<div class="actionButtons">
<h:commandButton id="save"
value="Save" action="#{masterEditor.persist}"
disabled="#{!masterEditor.wired}"
rendered="#{!masterEditor.managed}" />
<h:commandButton id="update"
value="Save" action="#{masterEditor.update}"
rendered="#{masterEditor.managed}" />
<h:commandButton id="delete"
value="Delete"
action="#{masterEditor.remove}"
immediate="true"
rendered="#{masterEditor.managed}" />
<s:button id="cancelEdit"
value="Cancel"
propagation="end"
view="/MasterList.xhtml" />
</div>
<div style="clear: both">
<span class="required">*</span>
required fields
</div>
</rich:panel>
</h:form>
</ui:define>
</ui:composition>
You'll note a number of CSS classes which modify the richfaces appearance:
.panelTopBorderOnly {
margin-top:10px;
border-left:none;
border-right:none;
border-bottom:none;
}
.panelTopBorderOnlyBodyClass {
padding-top:0px;
}
.detailList {
vertical-align:top;
width:200px;
height:200px;
overflow:scroll;
}
.detailDetail {
vertical-align:top;
}
input.buttonNoBorders {
margin:1px 1px 1px 0;
padding:0px;
}
Two key points:
- The ajax region was required to make the insert and delete of the Detail entities work when dealing with a freshly created Master entity.
- Note the buttons - these are done differently to the seam-gen buttons, because other the creation of a new Detail lost changes to the Master entity - if any.