Grails "render" renders the template

14,100

Solution 1

Resolved: Adding contentType results in the template not being rendered:

render text: "Name: ${person.name}", contentType: "text/plain"

Solution 2

Make your client side javascript code handle a JSON respond and render your response with:

render [text:"Name: ${person.name}"] as JSON

Solution 3

You might be getting burnt by the 'layout-by-convention' feature in Grails. If your layout name matches the controller name prefix, for example, Grails will apply the layout to every view managed by that controller. Unfortunately, it even applies to text and templates. There are currently a few JIRAs logged regarding this (see http://jira.grails.org/browse/GRAILS-7624 for example). I got burnt by this today. I resolved it by simply renaming my layout gsp such that it doesn't match any controller name. My layout was initially named 'storefront.gsp' and I have a controller named StorefrontController. I renamed the layout to 'public.gsp'.

Share:
14,100
Steve Kuo
Author by

Steve Kuo

Software, pilot, travel, life http://www.linkedin.com/in/stevekuo1

Updated on July 02, 2022

Comments

  • Steve Kuo
    Steve Kuo almost 2 years

    In my Grails controller I'm responding to an AJAX call and using render to return the text:

    def ajaxRandomPersonName = {
        def person = get a random person ...
        render "Name: ${person.name}"
    }
    

    The problem is that render renders the whole template. So instead of just rendering "Name: John" it renders all the icons, navigation, etc defined in the template. How do I get render to just render without the template?

    I'm pretty much following Chapter 1 of "Grails in Action" (page 28) using Grails 1.1.1.

    Follow up: Returning false per Rhysyngsun's suggestion has no impact. I also tried setting the template to null but it still renders the template:

    def ajaxRandomPersonName = {
        def person = get a random person ...
        render (template:null, text:"Name: ${person.name}")
    }
    

    render has its heart bent on rendering it through the template no matter what I do.

    Follow up 2: Parallel discussion on grails-user mailing list.

    Follow up 3: Sample code: I paired down my code the bare minimum and it still exhibits the undesired template rendering.

    controllers/PersonController.groovy:

    class PersonController { 
        def index = { } 
        def home = { [message:"Hello"] } 
    
        def ajaxTest = { 
            println "ajaxTest called" 
            render text: "ajax message" 
        } 
    } 
    

    views/person/home.gsp (view page for home method)

    <html> 
    <head> 
        <title>Home View</title> 
        <g:javascript library="prototype" /> 
    </head> 
    <body> 
        <p> 
            <g:remoteLink action="ajaxTest" update="test1">ajax call</g:remoteLink> 
        </p> 
        <p>Message = ${message}</p> 
        <p id="test1">Blank</p> 
    </body> 
    </html> 
    

    views/layouts/person.gsp (layout template for person controller)

    <html> 
    <head> 
        <title>Test App - <g:layoutTitle/></title> 
        <g:layoutHead/> 
    </head> 
    <body> 
        <h1>Test App</h1> 
        <g:layoutBody/> 
    </body> 
    </html> 
    

    I access person controller with the home view: http://localhost:8080/test/person/home

    the page renders as: Test App ajax call (hyperlink) Message = Hello Blank

    "Test App" is from the template. When I click "ajax call" it makes an asynchronous call to PersonController's ajaxTest method (verified with println). All ajaxTest does is println and render static text. This resultant in the following:

    Test App 
    ajax call 
    Message = Hello 
    Test App 
    ajax message 
    

    Note that the template is being rendered within "test1" <p> which results in the second "Test App".

    I'm running Grails 1.1.1. Any ideas? The code seems straightforward. I downloaded the Grails source and looked at RenderDynamicMethod.java. It doesn't do any template rendering unless template is in the argument list, which it isn't. So my only guess is something up steam is rendering the template again.

  • Steve Kuo
    Steve Kuo over 14 years
    I just tried returning false after render and it still renders the template.
  • Salman Paracha
    Salman Paracha over 12 years
    Yes, please elaborate on where you found this answer. On a side note, It's an absolute shame that chapter 1, which should have taken me 30 minutes, has taken me hours to complete. And, I am completely disappointed by my first stab at Grails