In order to
transition execution of a flow from one state to the next you need some way of trigger an
event that indicates what the flow should do next. Events can be triggered from either view states or action states.
Triggering Events from a View State
As discussed previously the start state of the flow in a previous code listing deals with two possible events. A
checkout
event and a
continueShopping
event:
def shoppingCartFlow = {
showCart {
on("checkout").to "enterPersonalDetails"
on("continueShopping").to "displayCatalogue"
}
…
}
Since the
showCart
event is a view state it will render the view
grails-app/book/shoppingCart/showCart.gsp
. Within this view you need to have components that trigger flow execution. On a form this can be done use the
submitButton tag:
<g:form action="shoppingCart">
<g:submitButton name="continueShopping" value="Continue Shopping"></g:submitButton>
<g:submitButton name="checkout" value="Checkout"></g:submitButton>
</g:form>
The form must submit back to the
shoppingCart
flow. The name attribute of each
submitButton tag signals which event will be triggered. If you don't have a form you can also trigger an event with the
link tag as follows:
<g:link action="shoppingCart" event="checkout" />
Triggering Events from an Action
To trigger an event from an
action
you need to invoke a method. For example there is the built in
error()
and
success()
methods. The example below triggers the
error()
event on validation failure in a transition action:
enterPersonalDetails {
on("submit") {
def p = new Person(params)
flow.person = p
if(!p.validate())return error()
}.to "enterShipping"
on("return").to "showCart"
}
In this case because of the error the transition action will make the flow go back to the
enterPersonalDetails
state.
With an action state you can also trigger events to redirect flow:
shippingNeeded {
action {
if(params.shippingRequired) yes()
else no()
}
on("yes").to "enterShipping"
on("no").to "enterPayment"
}