# formRemote

## Purpose

Creates a form tag that uses a remote uri to execute an ajax call serializing the form elements falling back to a normal form submit if javascript is not supported.

## Examples

Example controller for an application called "shop":

    class BookController {
         def list = { [ books: Book.list( params ) ] }
         def show = { [ book : Book.get( params['id'] ) ] }
    }

Example usages for above controller:

    <g:formRemote name="myForm" on404="alert('not found!')" update="updateMe" url="[action:'show']">
        Login: <input name="login" type="text"></input>
    </g:formRemote>
    <div id="updateMe">this div is updated by the form</div>

    <g:formRemote name="myForm" update="updateMe"
                  url="[ controller: 'book', action: 'list', params: [ sort: 'title', order: 'desc' ]]">
        Login: <input name="login" type="text"></input>
    </g:formRemote>
    <div id="updateMe">this div is updated by the form</div>

You can override both the form method and action to use when javascript is unavailable by providing `method` and `action` attributes. This example will submit the form to `/<context>/book/oldList` using a GET if javascript is unavailable:

    <g:formRemote name="myForm" method="GET" action="${createLink(controller: 'book', action: 'oldList')}"
                  url="[ controller: 'book', action: 'list', params: [ sort: 'title', order: 'desc' ]]">
        Login: <input name="login" type="text"></input>
    </g:formRemote>

## Description

Attributes

- `url` - The url to submit to as either a map (containing values for the controller, action, id, and params) or a URL string
- `action` (optional) - The action to execute as a fallback, defaults to the url if non specified
- `update` (optional) - Either a map containing the elements to update for 'success' or 'failure' states, or a string with the element to update in which cause failure events would be ignored
- `before` (optional) - The javascript function to call before the remote function call
- `after` (optional) - The javascript function to call after the remote function call
- `asynchronous` (optional) - Whether to do the call asynchronously or not (defaults to true)
- `method` (optional) - The method to use the execute the call (defaults to "post")

Events

- `onSuccess` (optional) - The javascript function to call if successful
- `onFailure` (optional) - The javascript function to call if the call failed
- `on_ERROR_CODE` (optional) - The javascript function to call to handle specified error codes (eg on404="alert('not found!')")
- `onUninitialized` (optional) - The javascript function to call the a ajax engine failed to initialise
- `onLoading` (optional) - The javascript function to call when the remote function is loading the response
- `onLoaded` (optional) - The javascript function to call when the remote function is completed loading the response
- `onComplete` (optional) - The javascript function to call when the remote function is complete, including any updates

## Source

Show Source

    def formRemote = { attrs, body ->
            if (!attrs.name) {
                throwTagError("Tag [formRemote] is missing required attribute [name]")
            }
            if (!attrs.url) {
                throwTagError("Tag [formRemote] is missing required attribute [url]")
            }        // 'formRemote' does not support the 'params' attribute.
            if (attrs.params != null) {
                throwTagError("""\
    Tag [formRemote] does not support the [params] attribute - add\
    a 'params' key to the [url] attribute instead.""")
            }        // get javascript provider
            def p = getProvider()
            def url = deepClone(attrs.url)        // prepare form settings
            p.prepareAjaxForm(attrs)        def params = [onsubmit:remoteFunction(attrs) + 'return false',
                          method: (attrs.method? attrs.method : 'POST' ),
                          action: (attrs.action? attrs.action : createLink(url))]
            attrs.remove('url')
            params.putAll(attrs)
            if (params.name && !params.id) {
                params.id = params.name
            }
            out << withTag(name:'form',attrs:params) {
                out << body()
            }
        }