////
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
////


== withFormat



=== Purpose


Renders different responses based on the incoming request `Accept` header, format parameter or URI extension. See link:{guidePath}theWebLayer.html#contentNegotiation[Content Negotiation] for more information.


=== Examples


[source,groovy]
----
import grails.converters.XML

class BookController {

    def list() {
        def books = Book.list()

        withFormat {
            html bookList:books
            js { render "alert('hello')" }
            xml { render books as XML }
        }
    }
}
----


=== Description


The `withFormat` accepts a Closure which contains methods corresponding to the different content types you want to respond to. For example:

[source,groovy]
----
withFormat {
    html bookList: books
    js { render "alert('hello')" }
    xml { render books as XML }
}
----

Here we invoke three methods called `html`, `js` and `xml` that use mime type names configured in `grails-app/conf/application.yml` (See link:{guidePath}theWebLayer.html#contentNegotiation[Content Negotiation] for more information). The call to `html` accepts a model (a Map) which is passed on to the view. Grails searches for a view called `grails-app/views/book/list.html.gsp` and if that is not found fallback to `grails-app/views/book/list.gsp`.

Note that the order of the types is significant if the request format is "all" or if more than one content type has the same "q" rating in the accept header. In the former case, the first type handler in the block is executed ("html" in the short example above). The latter case is more confusing because it only holds if there is more than one content type with the highest "q" rating for which you have a type handler *and* you have more than one type handler matching that "q" rating. For example if the request has "text/html" and "application/xml" with a "q" rating of 1.0, then this code:

[source,groovy]
----
withFormat {
    xml { ... }
    html { ... }
}
----

will use the "xml" type handler for the request.

Another important factor to note is that the `withFormat` method deals with the _response_ format and not the request format. As of Grails 2.0, there is a separate `withFormat` method made available on the `request` that you can use to handle the request format which is dictated by the `CONTENT_TYPE` header of the request:

[source,groovy]
----
request.withFormat {
    form { .. }
    xml { .. }
    json { .. }
}
----

NOTE: The request format of `form` is used for handling form submission in content negotiation as opposed to `html`.

If you require that the model be lazily executed you can pass a Closure instead of a Map:

[source,groovy]
----
withFormat {
    html { [bookList: Book.list()] }
    ...
}
----

This way the `html` Closure will only be executed if the `html` format is matched.

NOTE: Grails ignores the HTTP Accept header unless you add a `grails.mime.use.accept.header = true` setting to your `application.groovy` file. In other words, `withFormat()` will be completely unaffected by the Accept header without that setting.

[source,groovy]
----
grails.mime.use.accept.header = true
----

Or the equivalent in `application.yml`:

[source,yaml]
----
grails:
    mime:
        use:
            accept:
                header: true
----
