See the light - agile, industrial strength, rapid web application development made easy

(Quick Reference) # 7.5.2 Action States and View States - Reference Documentation Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith, Lari Hotari Version: 2.3.8 ## 7.5.2 Action States and View States #### View states A view state is a one that doesn't define an `action` or a `redirect`. So for example this is a view state:
    enterPersonalDetails {
       on("submit").to "enterShipping"
       on("return").to "showCart"
    }
It will look for a view called `grails-app/views/book/shoppingCart/enterPersonalDetails.gsp` by default. Note that the `enterPersonalDetails` state defines two events: `submit` and `return`. The view is responsible for triggering these events. Use the `render` method to change the view to be rendered:
    enterPersonalDetails {
       render(view: "enterDetailsView")
       on("submit").to "enterShipping"
       on("return").to "showCart"
    }
Now it will look for `grails-app/views/book/shoppingCart/enterDetailsView.gsp`. Start the `view` parameter with a / to use a shared view:
    enterPersonalDetails {
       render(view: "/shared/enterDetailsView")
       on("submit").to "enterShipping"
       on("return").to "showCart"
    }
Now it will look for `grails-app/views/shared/enterDetailsView.gsp` #### Action States An action state is a state that executes code but does not render a view. The result of the action is used to dictate flow transition. To create an action state you define an action to to be executed. This is done by calling the `action` method and passing it a block of code to be executed:
    listBooks {
       action {
          [bookList: Book.list()]
       }
       on("success").to "showCatalogue"
       on(Exception).to "handleError"
    }
As you can see an action looks very similar to a controller action and in fact you can reuse controller actions if you want. If the action successfully returns with no errors the `success` event will be triggered. In this case since we return a Map, which is regarded as the "model" and is automatically placed in flow scope. In addition, in the above example we also use an exception handler to deal with errors on the line:
    on(Exception).to "handleError"
This makes the flow transition to a state called `handleError` in the case of an exception. You can write more complex actions that interact with the flow request context:

    processPurchaseOrder {
        action {
            def a =  flow.address
            def p = flow.person
            def pd = flow.paymentDetails
            def cartItems = flow.cartItems
            flow.clear()        def o = new Order(person: p, shippingAddress: a, paymentDetails: pd)
            o.invoiceNumber = new Random().nextInt(9999999)
            for (item in cartItems) { o.addToItems item }
            o.save()
            [order: o]
        }
        on("error").to "confirmPurchase"
        on(Exception).to "confirmPurchase"
        on("success").to "displayInvoice"
    }
Here is a more complex action that gathers all the information accumulated from the flow scope and creates an `Order` object. It then returns the order as the model. The important thing to note here is the interaction with the request context and "flow scope". #### Transition Actions Another form of action is what is known as a transition action. A transition action is executed directly prior to state transition once an event has been triggered. A simple example of a transition action can be seen below:
    enterPersonalDetails {
       on("submit") {
           log.trace "Going to enter shipping"
       }.to "enterShipping"
       on("return").to "showCart"
    }
Notice how we pass a block of the code to `submit` event that simply logs the transition. Transition states are very useful for data binding and validation, which is covered in a later section. | Quick Reference (hide)