# form

## Purpose

Creates a form that submits to a controller, action, and/or id. Beyond what is below all the usual HTML attributes apply.

## Examples

Example controller for an application called "shop":

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

Example usages for above controller:

    <g:form name="myForm" action="myaction" id="1">...</g:form>
    results in:
    <form action="/shop/book/myaction/1" method="post" name="myForm" id="myForm" >...</form><g:form name="myForm" url="[action:'list',controller:'book']">...</g:form>
    results in:
    <form action="/shop/book/list" method="post" name="myForm" id="myForm" >...</form><g:form action="show">...</g:form>
    results in:
    <form action="/shop/book/show" method="post" >...</form>

## Description

Attributes

- `action` (optional) - the name of the action to use in the link, if not specified the default action will be linked
- `controller` (optional) - the name of the controller to use in the link, if not specified the current controller will be linked
- `id` (optional) - The id to use in the link
- `url` (optional) - A map containing the action,controller,id etc.
- `name` (optional) - A value to use for both the name and id attribute of the form tag
- `useToken` (optional) - Set whether to send a token in the request to handle duplicate form submissions. See Handling Duplicate Form Submissions

## Source

Show Source

    def form = {attrs, body ->        def useToken = attrs.remove('useToken')
            def writer = getOut()        writer << "<form action=\"${createLink(attrs)}\" "
            // default to post
            def method = attrs.remove('method')?.toUpperCase() ?: 'POST'
            def httpMethod = HttpMethod.valueOf(method)
            boolean notGet = httpMethod != HttpMethod.GET        if (notGet) {
                writer << 'method="post" '
            }
            else {
            	writer << 'method="get" '
            }
            // process remaining attributes
            attrs.id = attrs.id ? attrs.id : attrs.name
            if (attrs.id == null) attrs.remove('id')
            outputAttributes(attrs)        writer << ">"
            if (request['flowExecutionKey']) {
                writer.println()
                hiddenFieldImpl(writer, [name: "execution", value: request['flowExecutionKey']])
            }
            if(notGet && httpMethod != HttpMethod.POST) {
            	hiddenFieldImpl(writer, [name: "_method", value: httpMethod.toString()])
            }
            if(useToken) {
                def token = SynchronizerToken.store(session)
                writer.println()
                hiddenFieldImpl(writer, [name: SynchronizerToken.KEY, value: token.currentToken])
                writer.println()
                hiddenFieldImpl(writer, [name: SynchronizerToken.URI, value: request.forwardURI])
            }        // output the body
            writer << body()        // close tag
            writer << "</form>"
        }