Announcement Announcement Module
Collapse
No announcement yet.
JSF + Master-Detail Pattern Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • #16
    JSF master-detail

    In order to implement master-detail using JSF, I would suggest the following.

    Define 2 view-states

    1. view-state for displaying the master screen (JSF datatable) :

    Code:
    <view-state id="overview_contactinfo" view="/contactinfo.xhtml">
    <transition on="edit" to="edit_contactinfo">		
    <set attribute="contactInfoId" scope="flow" value="requestParameters.id"/>
    </transition>
    </view-state>
    On this view, an "edit" event can be triggered that will navigate the user to the detail screen. This will be triggered by an edit link that will be placed after each row in the table. A request param called id will be sent using <faram>, containing the object id.

    Code:
    <h:dataTable var="contactInfo" value="#{contactInfoList}">
    ....					
    <h:column>
    <h:commandLink value="Edit" action="edit">
    <f:param name="id" value="#{contactInfo.id}"/>
    </h:commandLink>
    </h:column>
    </h:datatable>

    Important to note here is that our request parameter will be sent with the request, and stored in flow-scope to make it available after the redirection to the detail screen.


    2. view-state for displaying the detail screen

    Code:
    <view-state id="edit_contactinfo" view="/editcontactinfo.xhtml">
    <transition on="submit" to="overview_contactinfo" />
    </view-state>
    This view just displays the detail screen. Keep in mind that we now have a contactInfoId attribute available here in flow scope.

    I typically use a detail backing bean to display my data on the detail screen. This bean will use setter injection to have a reference to the ID of the item that was selected :

    Code:
    <managed-bean>
    <managed-bean-name>contactInfoDetailBean</managed-bean-name>
    <managed-bean-class>ContactInfoDetailBean</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
    <managed-property>
    <property-name>id</property-name>
    <value>#{contactInfoId}</value>
    </managed-property>
    </managed-bean>

    JSF will resolve the #{contactInfoId} expression (remember, SWF has transferred our ID request param to a flow scope attribute), and the contactInfoDetailBean can implement logic to retrieve the object based on its ID.

    Comment


    • #17
      I did things in this way:

      Code:
      	<var name="clayxml$page3" bean="customerViewController" scope="flow" />
      
      	<start-state idref="start" />
      
      	<view-state id="start" view="/clayxml/page3.xml">
      		<transition on="edit" to="editCustomer" />
      		<transition on="cancel" to="endView" />
      	</view-state>
      
      	<subflow-state id="editCustomer" flow="edituser-flow">
      		<attribute-mapper>
      			<input-mapper>
      				<mapping source="${flowScope.clayxml$page3.theTable.rowData.Cust_ID}"
      					target="id" />
      			</input-mapper>
      		</attribute-mapper>
      		
      		<transition on="finish" to="start" />
      		<transition on="fail" to="endView" />
      	</subflow-state>
      	
      
      
      	<end-state id="endView" view="/clayxml/default.xml" />
      The detail view got something like this:

      Code:
      <var name="edit" class="de.sf.faces.beans.Customer" scope="flow" />
      
      	<input-mapper>
      		<input-attribute name="id" />
      	</input-mapper>
      
      	<start-state idref="start" />
      
      	<view-state id="start" view="/admin/editor-swf.xml">
      		<entry-actions>
      			<bean-action bean="customerProcessor" method="findCustomerById">
      				<method-arguments>
      					<argument expression="flowScope.id" />
      				</method-arguments>
      				<method-result name="edit" scope="flow" />
      			</bean-action>
      		</entry-actions>
      		<transition on="cancel" to="fail" />
      		<transition on="save" to="processCustomer" />
      	</view-state>
      	
      	<action-state id="processCustomer">
      		<bean-action bean="customerProcessor" method="save">
      			<method-arguments>
      				<argument expression="flowScope.edit" />
      			</method-arguments>
      		</bean-action>
      		<transition on="success" to="finish" />
      	</action-state>
      	
      	<end-state id="finish" />
      	<end-state id="fail" />
      Works fine.

      Don't know if this is the best way, comments are welcome.

      The best about flowScope vs. the requestScope variant from JSF only is, my ViewController on the list page has the same state before i want to see the details of a customer.
      Information about sorting etc. pp. is there.

      But there are some drawbacks - i am using the ViewController from Shale.
      prerender() / preprocess() does not work, so its nearly useless to use it - although "init" and "destroy" are working though - which is good, need to setup my transient SortModel there, as its not serializable.

      My customerDao is also not serializable, so its transient true.
      The bad about it, when i leave the detail view i get back to my list - the customerDao gots not saved, so i cant use it to update the list - and its not getting injected again like the first time the bean was created.
      So the "old" list data stuff is shown.

      Which would be the best way to solve this problem - returning to my list view, the updated entry should be shown, not the old one.
      I am new to Spring, so i may miss some basics and this is really to solve.
      Dao Managment is done like in the example application. So maybe someone got a nice idea to solve this.

      thx.

      Torsten

      Comment

      Working...
      X