I've asked myself several times why doesn't it support the main layout by convention? Maybe because of the partial pages retrieved by Ajax (like the <g:remoteLink> tag). Even on those cases, an heuristic might be applied to determine those cases. Let's go to the actual implementation:
Create a class called CustomLayoutDecoratorMapper on src/groovy:
import javax.servlet.ServletContext import javax.servlet.http.HttpServletRequest import org.codehaus.groovy.grails.web.sitemesh.GrailsLayoutDecoratorMapper import com.opensymphony.module.sitemesh.* import org.codehaus.groovy.grails.web.servlet.GrailsApplicationAttributes import org.codehaus.groovy.grails.web.metaclass.ControllerDynamicMethods class CustomLayoutDecoratorMapper extends GrailsLayoutDecoratorMapper { public Decorator getDecorator(HttpServletRequest request, Page page) { Decorator decorator = super.getDecorator(request, page) if (decorator == null) { decorator = getNamedDecorator(request, "main") } return decorator } }
Then reference it on web-app/WEB-INF/sitemesh.xml, by changing the mapper tag, so that it looks like this: <mapper class="CustomLayoutDecoratorMapper">. Note that when running grails upgrade the file will be reverted to it's original form!.
Ready! No more need to declare the layout on every page. But, if the layout is declared, it will be honored.
But what about the Ajax requests? I can think of 2 approaches: The first one is easier for people using the Prototype framework. Just change the line:
if (decorator == null) {
to:
if (decorator == null && request.getHeader("X-Requested-With") != "XMLHttpRequest") {
Prototype adds the header X-Requested-With: XMLHttpRequest for Ajax requests. I don't know whether Dojo does something like that...
The second option is to declare an empty layout on Ajax pages with <meta name="layout" content="empty">, and create the layout called empty only with the tag <g:layoutBody>.
Hope this helps!