8

I've looked around but could not find a way of simply including or rendering *.html files in Grails. My application needs to g.render or <g:render> templates which are delivered as html files. For this, as we know, html files have to be converted to _foo.gsp files in order to get rendered. I am totally surprised as to why isn't there a direct support for html or is there one??

Thanks!

sector7
  • 475
  • 1
  • 5
  • 9

6 Answers6

23

One obvious option is to simply rename your HTML files from foo.html to _foo.gsp and then use <render template="foo">. However this is so obvious that I'm sure you've already thought of it.

If you simply want to render a HTML file from within a controller you can use the text parameter of the render controller method

def htmlContent = new File('/bar/foo.html').text
render text: htmlContent, contentType:"text/html", encoding:"UTF-8"

If you want to do the same thing from within a .gsp, you could write a tag. Something like the following (untested) should work:

import org.springframework.web.context.request.RequestContextHolder

class HtmlTagLib {

  static namespace = 'html'

  def render = {attrs ->

    def filePath = attrs.file

    if (!file) {
      throwTagError("'file' attribute must be provided")
    }

    def htmlContent = new File(filePath).text
    out << htmlContent
  }
}

You can call this tag from a GSP using

<html:render file="/bar/foo.html"/>
Dónal
  • 185,044
  • 174
  • 569
  • 824
  • Thanks Don! This looks like it (the second part ie.). I'll give this a try and update my results here. – sector7 Feb 18 '10 at 07:33
  • Don - don't know if you'll see this, hope so. I tried the code you posted, but it seems like I have to specify a file relative to my computers root directory, e.g. "C:/grails2.0/..." How do I make it work relative to my webroot directory, like the render view currently works, looking for files under the appropriate view folder? – Ray Dec 24 '11 at 03:31
  • 1
    @Ray If you put the HTML files under web-app, you should be able to retrieve them using `g.resource` – Dónal Dec 24 '11 at 14:18
3

What is it you are trying to accomplish?

  1. Render html from a controller? In that case, all you should have to do is redirect the user to file from your control.

    redirect(uri:"/html/my.html")

  2. Use html-files instead of gsp template-files? Thing is, Grails is a "Convention over Configuration"-platform and that means you will have to do some things "the Grails way". The files needs the _ and the .gsp but the name can be whatever you like even if it's easier when you use the same name as the controller. What you gain from doing that is the knowledge that every developer that knows grails and comes into your project will understand how things are tied together and that will help them get started quickly.

Shashank Agrawal
  • 25,161
  • 11
  • 89
  • 121
xlson
  • 2,677
  • 1
  • 20
  • 11
  • In a real world scenario, might I say, things don't work according to rigid Conventions. A Framework should at least support working with its most fundamental elements - HTML in this case. Answering your question, we have a single GSP page wherein multiple Gauges are rendered. Each of these Gauges are pure _GSP_ templates BUT every once a while they need to be directly rendering HTML files which are dropped to a particular folder /some_folder/*.html In the TAGLIB which I've created we need to toggle between rendering from GSP templates or HTML files. Apologies for not clearing this first. – sector7 Feb 18 '10 at 07:32
  • Thanks for clearing that up. Don's answer seems like a good fit for you and honestly your need is specific enough to warrant it's own custom taglib. – xlson Feb 18 '10 at 12:40
1

Little bit fixed the Don's example, works fine for me

import org.apache.commons.io.IOUtils

class HtmlTagLib {

    static namespace = 'html'

    def render = {attrs ->

        def filePath = attrs.file

        if (!filePath) {
            throwTagError("'file' attribute must be provided")
        }
        IOUtils.copy(request.servletContext.getResourceAsStream(filePath), out);
    }
}
jozh
  • 2,412
  • 2
  • 15
  • 15
1

I wanted to write static html/ajax pages hosted in grails app (v2.4.4), but use the controller for the url rewrite. I was able to accomplish this by moving the file to web-app/ (for ease of reference), and simply use the render() method with 'file' and 'contentType' params, such as:

// My controller action
def tmp() {
    render file: 'web-app/tmp.html', contentType: 'text/html'
}

Note: I only tried this using run-app, and haven't packaged a war and deployed to tomcat, yet.

Doc: http://grails.github.io/grails-doc/2.4.4/ref/Controllers/render.html

Scott Langeberg
  • 189
  • 1
  • 7
0
  Closure include = { attr ->
        out << Holders.getServletContext().getResource(attr.file).getContent();
    }

It is relative to the web-app folder of your grails main application

mjs
  • 21,431
  • 31
  • 118
  • 200
  • i modified your approach to allow inclusion of external files for grails rendering plugin, where network paths would get botched in higher environments - mine ended up like: `def includeFile = { attr -> URL resource = Holders.getServletContext().getResource(attr.file) InputStream content = resource.getContent() String text = content?.text log.info "includeFile($attr) - resource: $resource, content.text.size(): ${text?.size()}" out << text }` – Scott Langeberg Sep 24 '15 at 17:15
0

I was able to use @momo's approach to allow inclusion of external files for grails rendering plugin, where network paths would get botched in higher environments - mine ended up like:

def includeFile = { attr ->
    URL resource = Holders.getServletContext().getResource(attr.file)
    InputStream content = resource.getContent()
    String text = content?.text
    log.info "includeFile($attr) - resource: $resource, content.text.size(): ${text?.size()}"
    out << text
}
Scott Langeberg
  • 189
  • 1
  • 7