grails taglib « Intelligrape Groovy & Grails Blogs

Posts Tagged ‘ grails taglib ’

Redis: Heavyweight Tags – an awesome use-case for caching with Redis

Posted by on September 25th, 2012

Redis plugin provides a beautiful way to cache the html tags. Using this plugin we can make big savings on the time taken to render the gsp tags.

<redis:memoize  key="someKey" expire="3600" >
   //Some heavy weight tags rendering
  // Lots of db / network operations.
</redis:memoize>

I found this tag extremely helpful in rendering the public facing pages of our site. the pages which refreshed not very frequently and required few seconds to render(if done without caching).

The difference in the time taken to render the page is dependent on our choice of right candidate for Memoizing.

(more…)

Posted in Design Pattern, Grails

Using TagLib to avoid changes due to change in URLMappings

Posted by on February 14th, 2011

Recently, I used Taglib to centralize the effect of URL mapping related changes of my grails application.

def userPageLink = {attrs, body ->

def user = User.read(attrs.id)

out << g.link(controller: 'user', action: 'show', params: [name: user.name]) {body()}
}

So wherever I need a link to user page, I can use this Taglib instead of g:link.

<hys:userPageLink id="${user.id}">${user.name}</hys:userPageLink>

Advantage:


Whenever I change the URL Mappings, there is no need to update all the g:link in all my gsp files. I would just update my taglib to cater to new URL Mapping.

Posted in Grails

Grails taglib and JavaScript file

Posted by on January 16th, 2011

We use internationalization feature in grails using message tag in GSP pages. However arbitrary Groovy/Grails (e.g. tags) code can not be used in JavaScript as they are not executed on server side. To overcome this I used the following way :

Declare a JSON object in js file or any where else so that this object is global one. Create a global JavaScript function that can populate this JSON object. Here is the sample code:


var i18nmessages={};

function updateConfigurationMap(newConfigurationMap) {
	for(key in newConfigurationMap){
		i18nmessages[key] = newConfigurationMap[key];
	}
/*
	//or in jQuery way
	jQuery.each(newConfiguration, function(key, val) {
		i18nmessages[key] = val
	});
*/
}

Now you can write code like below inside HTML head tag in GSP pages to populate the i18nmessages JSON map:


<script type="text/javascript">

 updateConfigurationMap({

   noResultError : '${message(code:'project.noResultError'')}.encodeAsHTML()',

   rangeError : '${message(code:'project.rangeError', args:[50, 100]).encodeAsHTML()}',

   ajaxCallUrl : '${createLink(controller:'myController', action: 'myAction')}',

   deleteImagePath : '${resource(dir:'images', file:'myimage.png')}'

 });

</script>

After execution of the above GSP code considering that the JavaScript code written above has executed, you can use messages like this in javascript :


function findResult(){
	alert("Error occurred during processing : "+i18nmessages.noResultError)
}

function getRemoteData(dataToSend){
       /*  note that you can not use createLink grails tag here  */
	jQuery.get(i18nmessages.ajaxCallUrl+"?"+dataToSend, function(response){
		// Process response here.
	})
}

function insertDeleteImage(){
       /* As you can not use resource tag of grails here */
	jQuery('selector').append("<img src='"+ i18nmessages.deleteImagePath +"' />")
}

Obviously there is a drawback with this approach that the JavaScript for setting messages can not be cached in browser. But the advantage is that you are free to use arbitrary Server side code to generate messages. As you have noticed in above code snippet the URL for ajax call and image paths generated using Grails tags can not be used inside the js files.

Another idea will be to create separate js files name ending with language suffix(e.g. *-en.js, *-sv.js etc) for each language your app support. Populate the i18nmessages there. Use appropriate js file depending on the request locale(e.g. session.'org.springframework.web.servlet.i18n.SessionLocaleResolver.LOCALE'). This way you can enable caching of js files in browser but you are limited to messages with static content only.



Please share your ideas how you solved this situation.


Cheers!
~~Bhagwat Kumar~~
bhagwat(at)intelligrape(dot)com

Cheers!
~~Bhagwat Kumar~~
bhagwat(at)intelligrape(dot)com
http://twitter.com/bhagwatkumar
http://in.linkedin.com/in/bhagwatkumar

Test Link

Posted by on April 19th, 2010

(based on Tomás Lin’s truthlink)

This is useful when one requires link on certain condition.
Instead of first using condition tag and then tag for link these can be combined into one using taglib.

<g:if test=${condition> 
    <g:link controller:'controllerName' action:'actionName'> 
	text 
    </g:link> 
<g:if>

or

<g:if test=${condition}>   
   <a href="#" class="abc" style="color:#90B8FF;"> 
     Text 
   </a> 
<g:if>

Other way of doing this is by using taglib.

class AbcTagLib {
namespaces "abc";
 
    def testLink = {attrs, body ->
        String attributes = ''
        if (attrs['test']) {
            attrs.remove('test')
           if (attrs.keySet().contains("action") || attrs.keySet().contains("controller")) {
                out << g.link(attrs, body)
            } else {
                attributes = "${attrs.collect {k, v -> " $k=\"$v\"" }.join('')}>"
                out << "<a " + attributes + body() + "</a>"
            }
 
        } else {
            out << body()
        }
    }
}

Now since the Tag is created condition test and and link can be combined into one

<abc:testLink test="${condition}" controller:'controllerName' action:'actionName'>
text                                        
</abc:testLink>

or

<abc:testLink test=${condition} href="#" class="abc" style="color:#90B8FF;"> 
     Text 
</abc:testLink>

_____________________
Hitesh Bhatia
hitesh@intelligrape.com
_____________________

Posted in Grails, Groovy