////
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.
////


==== Creating Layouts

Grails uses the https://github.com/sitemesh/sitemesh3[SiteMesh 3] framework as its decorator engine to support view layouts. In Grails 7.2 and later, decoration is performed by a Spring MVC `ViewResolver` rather than a Servlet filter, which improves performance and enables correct support for async controller return types.

Layouts are located in the `grails-app/views/layouts` directory. A typical layout can be seen below:

[source,xml]
----
<html>
    <head>
        <title><g:layoutTitle default="An example decorator" /></title>
        <g:layoutHead />
    </head>
    <body onload="${pageProperty(name:'body.onload')}">
        <div class="menu"><!--my common menu goes here--></div>
        <div class="body">
            <g:layoutBody />
        </div>
    </body>
</html>
----

The key elements are the link:{gspTagsRef}layoutHead.html[layoutHead], link:{gspTagsRef}layoutTitle.html[layoutTitle] and link:{gspTagsRef}layoutBody.html[layoutBody] tag invocations:

* `layoutTitle` - outputs the target page's title
* `layoutHead` - outputs the target page's head tag contents
* `layoutBody` - outputs the target page's body tag contents

The previous example also demonstrates the link:{gspTagsRef}pageProperty.html[pageProperty] tag which can be used to inspect and return aspects of the target page.


==== Triggering Layouts


There are a few ways to trigger a layout. The simplest is to add a meta tag to the view:

[source,xml]
----
<html>
    <head>
        <title>An Example Page</title>
        <meta name="layout" content="main" />
    </head>
    <body>This is my content!</body>
</html>
----

In this case a layout called `grails-app/views/layouts/main.gsp` will be used to lay out the page. If we were to use the layout from the previous section the output would resemble this:

[source,xml]
----
<html>
    <head>
        <title>An Example Page</title>
    </head>
    <body onload="">
        <div class="menu"><!--my common menu goes here--></div>
        <div class="body">
            This is my content!
        </div>
    </body>
</html>
----


==== Specifying A Layout In A Controller


Another way to specify a layout is to specify the name of the layout by assigning a value to the "layout" property in a controller. For example, if you have a controller such as:

[source,groovy]
----
class BookController {
    static layout = 'customer'

    def list() { /*...*/ }
}
----

You can create a layout called `grails-app/views/layouts/customer.gsp` which will be applied to all views that the `BookController` delegates to.  The value of the `layout` property may contain a directory structure relative to the `grails-app/views/layouts/` directory.  For example:

[source,groovy]
----
class BookController {
    static layout = 'custom/customer'

    def list() { /*...*/ }
}
----

Views rendered from that controller would be decorated with the `grails-app/views/layouts/custom/customer.gsp` template.


==== Layout by Convention


Another way to associate layouts is to use "layout by convention". For example, if you have this controller:

[source,groovy]
----
class BookController {
    def list() { /*...*/ }
}
----

You can create a layout called `grails-app/views/layouts/book.gsp`, which will be applied to all views that the `BookController` delegates to.

Alternatively, you can create a layout called `grails-app/views/layouts/book/list.gsp` which will only be applied to the `list` action within the `BookController`.

If you have both the above-mentioned layouts in place the layout specific to the action will take precedence when the list action is executed.

If a layout is not located using any of those conventions, the convention of last resort is to look for the application default layout which
is `grails-app/views/layouts/application.gsp`.  The name of the application default layout may be changed by defining the property `grails.sitemesh.default.layout`
in the application configuration as follows:

[source,yaml]
.grails-app/conf/application.yml
----
grails:
    sitemesh:
        default:
            layout: myLayoutName
----

With that property in place, the application default layout will be `grails-app/views/layouts/myLayoutName.gsp`.

NOTE: In Grails 7.2+ the canonical property for the default layout is `grails.sitemesh.default.layout`. The older `grails.views.layout.default` key is no longer consulted by the SiteMesh 3 integration.


==== Inline Layouts


Grails also supports inline layouts with the link:{gspTagsRef}applyLayout.html[applyLayout] tag. This can be used to apply a layout to a template, URL or arbitrary section of content. This lets you even further modularize your view structure by "decorating" your template includes.

Some examples of usage can be seen below:

[,xml]
----
<g:applyLayout name="myLayout" template="bookTemplate" collection="${books}" />

<g:applyLayout name="myLayout" url="https://www.google.com" />

<g:applyLayout name="myLayout">
The content to apply a layout to
</g:applyLayout>
----


==== Server-Side Includes


While the link:{gspTagsRef}applyLayout.html[applyLayout] tag is useful for applying layouts to external content, if you simply want to include external content in the current page you use the link:{gspTagsRef}include.html[include] tag:

[source,xml]
----
<g:include controller="book" action="list" />
----

You can even combine the link:{gspTagsRef}include.html[include] tag and the link:{gspTagsRef}applyLayout.html[applyLayout] tag for added flexibility:

[source,xml]
----
<g:applyLayout name="myLayout">
   <g:include controller="book" action="list" />
</g:applyLayout>
----

Finally, you can also call the link:{gspTagsRef}include.html[include] tag from a controller or tag library as a method:

[source,groovy]
----
def content = include(controller:"book", action:"list")
----

The resulting content will be provided via the return value of the link:{gspTagsRef}include.html[include] tag.


==== SiteMesh 2 Attribution (grails-layout)

The legacy `grails-layout` plugin remains available for applications that have not yet migrated to the SiteMesh 3 integration. When `grails-layout` is on the classpath, decoration is provided by SiteMesh 2 and the following attribution applies:

[NOTE]
====
This product includes software developed by the OpenSymphony Group (https://github.com/sitemesh). The SiteMesh 2 framework is licensed under the OpenSymphony Software License, Version 1.1.
====

This acknowledgment is required by the OpenSymphony Software License when redistributing SiteMesh 2 and applies only to applications that include the `grails-layout` plugin. Applications using only the SiteMesh 3 integration are not subject to this requirement.
