-Reorganized the main flow to show the hotel search results on a seperate page, showing the ability to use AJAX to render a partial view fragment into a nice javascript dialog box if javascript is turned on, but perform a full page refresh if it is turned off.
This commit is contained in:
@@ -7,6 +7,7 @@ import java.util.List;
|
||||
import javax.faces.event.ActionEvent;
|
||||
import javax.faces.model.SelectItem;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.webflow.samples.booking.app.BookingService;
|
||||
|
||||
/**
|
||||
@@ -95,4 +96,14 @@ public class SearchCriteria implements Serializable {
|
||||
}
|
||||
return pageSizeOptions;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer criteria = new StringBuffer();
|
||||
if (StringUtils.hasText(searchString)) {
|
||||
criteria.append("Text: " + searchString + ", ");
|
||||
}
|
||||
criteria.append("Page Size: " + pageSize);
|
||||
return criteria.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
<!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:ui="http://java.sun.com/jsf/facelets"
|
||||
xmlns:h="http://java.sun.com/jsf/html"
|
||||
xmlns:f="http://java.sun.com/jsf/core"
|
||||
xmlns:sf="http://www.springframework.org/tags/faces"
|
||||
template="/template.xhtml">
|
||||
|
||||
<ui:define name="content">
|
||||
<h:form id="displayHotelsForm">
|
||||
<div class="section">
|
||||
<sf:commandLink ajaxEnabled="false" value="Return to Main" action="changeSearch"/>
|
||||
<h2>Hotel Results</h2>
|
||||
<p>
|
||||
<b>Search Criteria:</b> #{searchCriteria}<br/>
|
||||
<sf:commandLink value="Edit Criteria" onclick="dijit.byId('dialog1').show();" action="changeSearch" renderIds="hotelSearchFragment"/>
|
||||
</p>
|
||||
<h:outputText id="noHotelsTxt" value="No Hotels Found" rendered="#{hotels.rowCount==0}"/>
|
||||
<h:dataTable id="hotels" styleClass="summary" value="#{hotels}" var="hotel" rendered="#{hotels.rowCount > 0}">
|
||||
<h:column>
|
||||
<f:facet name="header">Name</f:facet>
|
||||
#{hotel.name}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Address</f:facet>
|
||||
#{hotel.address}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">City, State</f:facet>
|
||||
#{hotel.city}, #{hotel.state}, #{hotel.country}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Zip</f:facet>
|
||||
#{hotel.zip}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Action</f:facet>
|
||||
<!-- @TODO - THIS LINK DOES NOT WORK ON MYFACES 1.2.0 WHEN AJAX IS ENABLED BECAUSE THEY HAVE NOT IMPLEMENTED UIData.invokeOnComponent -->
|
||||
<sf:commandLink id="viewHotelLink" value="View Hotel" ajaxEnabled="false" action="selectHotel"/>
|
||||
</h:column>
|
||||
</h:dataTable>
|
||||
<div class="next">
|
||||
<sf:commandLink id="nextPageLink" value="More Results" actionListener="#{searchCriteria.nextPageListener}"
|
||||
rendered="#{not empty hotels and hotels.rowCount == searchCriteria.pageSize}"
|
||||
processIds="displayHotelsForm"/>
|
||||
</div>
|
||||
<div class="prev">
|
||||
<sf:commandLink id="prevPageLink" value="Previous results" actionListener="#{searchCriteria.prevPageListener}"
|
||||
rendered="#{searchCriteria.page > 0}"
|
||||
processIds="displayHotelsForm"/>
|
||||
</div>
|
||||
</div>
|
||||
</h:form>
|
||||
<script type="text/javascript">
|
||||
dojo.require("dijit.Dialog");
|
||||
dojo.require("dojo.parser");
|
||||
</script>
|
||||
<div dojoType="dijit.Dialog" id="dialog1" title="First Dialog">
|
||||
<div id="hotelSearch"> </div>
|
||||
</div>
|
||||
</ui:define>
|
||||
</ui:composition>
|
||||
@@ -7,121 +7,81 @@
|
||||
template="/template.xhtml">
|
||||
|
||||
<ui:define name="content">
|
||||
<h:form id="mainForm">
|
||||
<ui:fragment id="hotelSearchFragment">
|
||||
<div id="hotelSearch" class="section">
|
||||
<span class="errors">
|
||||
<h:messages globalOnly="true"/>
|
||||
</span>
|
||||
<h2>Search Hotels</h2>
|
||||
|
||||
<div class="section">
|
||||
<span class="errors">
|
||||
<h:messages globalOnly="true"/>
|
||||
</span>
|
||||
<h2>Search Hotels</h2>
|
||||
<div id="hotelsearch">
|
||||
<br/>
|
||||
<br/>
|
||||
<fieldset>
|
||||
<div class="searchGroup">
|
||||
<div class="searchField">
|
||||
<sf:clientTextValidator promptMessage="Search hotels by name, address, city or zip.">
|
||||
<h:inputText id="searchString" value="#{searchCriteria.searchString}" style="width: 165px; height: 15px;"/>
|
||||
</sf:clientTextValidator>
|
||||
</div>
|
||||
<div class="searchSize">
|
||||
<h:outputLabel for="pageSize">Maximum results:</h:outputLabel>
|
||||
<sf:ajaxEvent actionListener="#{searchCriteria.findHotelsListener}" action="findHotels"
|
||||
event="onchange" processIds="mainForm:searchString, mainForm:pageSize, mainForm:hotelsSection" renderIds="mainForm:hotelsSection">
|
||||
<h:selectOneMenu value="#{searchCriteria.pageSize}" id="pageSize">
|
||||
<f:selectItem itemLabel="5" itemValue="5"/>
|
||||
<f:selectItem itemLabel="10" itemValue="10"/>
|
||||
<f:selectItem itemLabel="20" itemValue="20"/>
|
||||
</h:selectOneMenu>
|
||||
</sf:ajaxEvent>
|
||||
</div>
|
||||
<div class="searchButton">
|
||||
<sf:commandButton id="findHotels" value="Find Hotels" actionListener="#{searchCriteria.findHotelsListener}" action="findHotels"
|
||||
processIds="mainForm:searchString, mainForm:pageSize, mainForm:hotelsSection" renderIds="mainForm:hotelsSection"/>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<ui:fragment id="hotelsSection">
|
||||
<div id="hotelsPlaceholder">
|
||||
<h:outputText id="noHotelsTxt" value="No Hotels Found" rendered="#{hotels.rowCount==0}"/>
|
||||
<h:dataTable id="hotels" styleClass="summary" value="#{hotels}" var="hotel" rendered="#{hotels.rowCount > 0}">
|
||||
<h:column>
|
||||
<f:facet name="header">Name</f:facet>
|
||||
#{hotel.name}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Address</f:facet>
|
||||
#{hotel.address}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">City, State</f:facet>
|
||||
#{hotel.city}, #{hotel.state}, #{hotel.country}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Zip</f:facet>
|
||||
#{hotel.zip}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Action</f:facet>
|
||||
<!-- @TODO - THIS LINK DOES NOT WORK ON MYFACES 1.2.0 WHEN AJAX IS ENABLED BECAUSE THEY HAVE NOT IMPLEMENTED UIData.invokeOnComponent -->
|
||||
<sf:commandLink id="viewHotelLink" value="View Hotel" ajaxEnabled="false" action="selectHotel"/>
|
||||
</h:column>
|
||||
</h:dataTable>
|
||||
<div class="next">
|
||||
<sf:commandLink id="nextPageLink" value="More Results" actionListener="#{searchCriteria.nextPageListener}" action="findHotels"
|
||||
rendered="#{not empty hotels and hotels.rowCount == searchCriteria.pageSize}"
|
||||
processIds="mainForm:hotelsSection"/>
|
||||
</div>
|
||||
<div class="prev">
|
||||
<sf:commandLink id="prevPageLink" value="Previous results" actionListener="#{searchCriteria.prevPageListener}" action="findHotels"
|
||||
rendered="#{searchCriteria.page > 0}"
|
||||
processIds="mainForm:hotelsSection"/>
|
||||
</div>
|
||||
<h:form id="mainForm">
|
||||
<br/>
|
||||
<br/>
|
||||
<fieldset>
|
||||
<div class="searchGroup">
|
||||
<div class="searchField">
|
||||
<sf:clientTextValidator promptMessage="Search hotels by name, address, city or zip.">
|
||||
<h:inputText id="searchString" value="#{searchCriteria.searchString}" style="width: 165px; height: 15px;"/>
|
||||
</sf:clientTextValidator>
|
||||
</div>
|
||||
<div class="searchSize">
|
||||
<h:outputLabel for="pageSize">Maximum results:</h:outputLabel>
|
||||
<h:selectOneMenu value="#{searchCriteria.pageSize}" id="pageSize">
|
||||
<f:selectItem itemLabel="5" itemValue="5"/>
|
||||
<f:selectItem itemLabel="10" itemValue="10"/>
|
||||
<f:selectItem itemLabel="20" itemValue="20"/>
|
||||
</h:selectOneMenu>
|
||||
</div>
|
||||
<div class="searchButton">
|
||||
<sf:commandButton id="findHotels" value="Find Hotels" ajaxEnabled="false" actionListener="#{searchCriteria.findHotelsListener}" action="findHotels"/>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</h:form>
|
||||
|
||||
</div>
|
||||
</ui:fragment>
|
||||
</div>
|
||||
|
||||
<ui:fragment id="bookingsSection">
|
||||
<div class="section">
|
||||
<h2>Current Hotel Bookings</h2>
|
||||
|
||||
<h:outputText value="No Bookings Found" rendered="#{bookings.rowCount == 0}"/>
|
||||
<h:dataTable id="bookings" styleClass="summary" value="#{bookings}" var="booking" rendered="#{bookings.rowCount > 0}">
|
||||
<h:column>
|
||||
<f:facet name="header">Name</f:facet>
|
||||
#{booking.hotel.name}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Address</f:facet>
|
||||
#{booking.hotel.address}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">City, State</f:facet>
|
||||
#{booking.hotel.city}, #{booking.hotel.state}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Check in date</f:facet>
|
||||
<h:outputText value="#{booking.checkinDate}"/>
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Check out date</f:facet>
|
||||
<h:outputText value="#{booking.checkoutDate}"/>
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Confirmation number</f:facet>
|
||||
#{booking.id}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Action</f:facet>
|
||||
<!-- @TODO - THIS LINK DOES NOT WORK ON MYFACES 1.2.0 WHEN AJAX IS ENABLED BECAUSE THEY HAVE NOT IMPLEMENTED UIData.invokeOnComponent -->
|
||||
<sf:commandLink id="cancel" value="Cancel" ajaxEnabled="false" action="cancelBooking"/>
|
||||
</h:column>
|
||||
</h:dataTable>
|
||||
</div>
|
||||
</ui:fragment>
|
||||
|
||||
</h:form>
|
||||
<ui:fragment id="bookingsSection">
|
||||
<div class="section">
|
||||
<h:form id="bookingsForm">
|
||||
<h2>Current Hotel Bookings</h2>
|
||||
|
||||
<h:outputText value="No Bookings Found" rendered="#{bookings.rowCount == 0}"/>
|
||||
<h:dataTable id="bookings" styleClass="summary" value="#{bookings}" var="booking" rendered="#{bookings.rowCount > 0}">
|
||||
<h:column>
|
||||
<f:facet name="header">Name</f:facet>
|
||||
#{booking.hotel.name}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Address</f:facet>
|
||||
#{booking.hotel.address}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">City, State</f:facet>
|
||||
#{booking.hotel.city}, #{booking.hotel.state}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Check in date</f:facet>
|
||||
<h:outputText value="#{booking.checkinDate}"/>
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Check out date</f:facet>
|
||||
<h:outputText value="#{booking.checkoutDate}"/>
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Confirmation number</f:facet>
|
||||
#{booking.id}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Action</f:facet>
|
||||
<!-- @TODO - THIS LINK DOES NOT WORK ON MYFACES 1.2.0 WHEN AJAX IS ENABLED BECAUSE THEY HAVE NOT IMPLEMENTED UIData.invokeOnComponent -->
|
||||
<sf:commandLink id="cancel" value="Cancel" ajaxEnabled="false" processIds="bookingsSection" action="cancelBooking"/>
|
||||
</h:column>
|
||||
</h:dataTable>
|
||||
</h:form>
|
||||
</div>
|
||||
</ui:fragment>
|
||||
</ui:define>
|
||||
|
||||
</ui:composition>
|
||||
@@ -17,18 +17,21 @@
|
||||
|
||||
<view-state id="displayMain" view="main.xhtml">
|
||||
<transition on="findHotels" to="findHotels" />
|
||||
<transition on="selectHotel" to="displayHotel">
|
||||
<set attribute="#{hotel}" value="#{hotels.selectedRow}" scope="flash"/>
|
||||
</transition>
|
||||
<transition on="cancelBooking" to="cancelBooking" />
|
||||
</view-state>
|
||||
|
||||
<action-state id="findHotels">
|
||||
<action method="findHotels" bean="mainActions" />
|
||||
<transition on="success" to="displayMain" />
|
||||
</action-state>
|
||||
<view-state id="findHotels" view="displayHotels.xhtml">
|
||||
<render-actions>
|
||||
<action method="findHotels" bean="mainActions" />
|
||||
</render-actions>
|
||||
<transition on="selectHotel" to="displayHotel"/>
|
||||
<transition on="changeSearch" to="displayMain"/>
|
||||
</view-state>
|
||||
|
||||
<view-state id="displayHotel" view="hotelDetails.xhtml">
|
||||
<render-actions>
|
||||
<set attribute="#{hotel}" value="#{hotels.selectedRow}" scope="request"/>
|
||||
</render-actions>
|
||||
<transition on="book" to="bookHotel" />
|
||||
<transition on="cancel" to="displayMain" />
|
||||
</view-state>
|
||||
|
||||
Reference in New Issue
Block a user