Question

There are essentially 2 places to define JavaScript functions in Grails, directly in a element on the GSP, and within a separate javascript source file under /web-app/js (for example, application.js). We have defined a commonly reused javascript function within application.js, but we also need to be able to generate parts of the function dynamically using groovy code. Unfortunately, ${some groovy code} does not appear to be processed within separate javascript source files.

Is the only way to do this by defining the javascript function within a script tag on a GSP page, or is there a more general solution? Obviously we could define the javascript function in a script tag within a template GSP file which would be reused, but there is a lot of push to keep our javascript functions defined all together in one place (i.e. the external javascript source file). This has performance benefits as well (the javascript source files are usually just downloaded once by each client's browser, instead of reloading the same javascript functions within the source of every html page they visit). I have toyed around with the idea of breaking the function up into static and dynamic pieces, putting the static ones in the external source and putting the dynamic ones in the template GSP, then gluing them together, but this seems like an unnecessary hack.

Any ideas?

(edit: It may sound like the idea of dynamically generating parts of a JavaScript function, which is then downloaded once and used over and over again by the client, would be a bad idea. However, the piece which is "dynamic" only changes perhaps once a week or month, and then only very slightly. Mostly we just want this piece generated off the database, even if only once, instead of hard coded.)

Was it helpful?

Solution

An easy solution to keep your JavaScript unobtrusive is to create a JavaScriptController and map its actions "/js/*" by adding this to your UrlMappings.groovy file:

"/js/$action"{
  controller = "javascript"
}

then just create an action for each dynamic JS file you want, include in in your layout <HEAD>, and presto, you've got a JS file that you can insert Grails snippets into! :)

Note: I've found that there's currently a bug in Grails that doesn't map file extensions to content-types properly, so you'll need to include <%@ page contentType="text/javascript; UTF-8" %> at the top of your view files.

OTHER TIPS

This is a great solution. I would like to offer a suggestion to use somthing other then a mapping of

"/js/$action" 
because this is no longer going to allow you to access you javascript files in /web-app/js/. All your javascript files would have to be moved to a the directory your controller would point to.

I would use something like

"/dynjs/$action"

This way you still can point to files in the /web-app/js/ files with out conflict and enjoy the benifits of gsp tags in javascript files

Please correct me if I'm wrong.

Or this... have a tag/service/dynamic method that lets tags write out their JS+CSS+whatever else, to a "cache" which is used to build the JS+CSS resources by a different controller.

Full concept here: [http://www.anyware.co.uk/2005/2009/01/19/an-idea-to-give-grails-tags-esp/][1]

If you want to use models created by the controller (that rendered HTML page which reference the Javascript in which you intend to use groovy code) in the Javascript code, then you can use this technique:

This technique does not need to change URL mappings and does not require you to create extra controller.

In your view GSP add javascript as follows:

    <script type="text/javascript">
        <g:render template="/javascript/yourJavascriptFile"/>
    </script>

In views folder create a "javascript" folder. And create a file named: _yourJavascriptFile.gsp

You can not only use all the GSP code in your _yourJavascriptFile.gsp file, but you can also use all the models created in your controller (that is rendering the view).

NOTE: There is nothing special about javascript folder. You can name it anything you want OR use an existing view folder. This is just a matter of organizing and identifying your HTML spitting GSP from Javascript spitting GSPs. Alternatively, you can use some naming conventions like: _something.js.gsp etc.

Name your scripts like this

/wherever/the/js/files/are/thescript.js.gsp

The gsp code inside will be rendered correctly by grails. This works, but I have no idea if it's considered a Good Idea or not.

There is another way - pass in the generated code into a function that expects closures. Those closures is generated by the program of course. The generated code is of course inlined/script-tagged in the gsp page.

it may or may not work depending on the nature of the code being generated. But i suspect it will work, and if it doesnt, minor tweaking to the coding style of your javascript will definitely make it work. Though, if these 'generated' code doesnt change much, this quite overkill imo.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top