The other day I was reading the Grails docs and I came across a useful GSP tag: grep. I have been using Grails for over 3 years now but just recently got to see this new tag which has eased my life a bit in situations where the list of objects have to be filtered and iterated at the same time to perform some operations on them. The GSP ‘grep’ tag (equivalent to the ‘grep’ method in Groovy) filters the list on a given condition and iterates over the filtered list allowing you to do some operations on the objects (or whatever you want to do with the filtered objects).
I will give you a small example: Suppose we have a list of Person objects. You want to display the names starting with A, B, C and so on in different color schemes. How would you do it?
One implementation is to send different lists from the controllers (this would mean sending 26 lists i.e. one list for each character in the English alphabet) and render them in different color schemes. The other way would be to iterate over the Persons list in the GSP and have different <g:if>…<:g:elseif> statements (for each character).
There is another smarter way: you could also use the ‘findAll‘ method of the List in the GSP <g:each> tag’s ‘in’ attribute i.e <g:each in=${personList.findAll {it.name.startsWith(‘A’)}} var=”person”> … </g:each>.
Similarly, we can use ‘grep’ tag here. We can filter out the list like this: <g:grep in=”${personList.name}” filter=”~/^A.*/”> … </g:grep>.
Notice the use of ‘name‘ field of the Person object in the ‘in‘ attribute of the grep tag. Also, the attribute ‘filter’ takes many forms of filter options; here we are using regex to filter the persons with the name starting with ‘A’.
I am not saying that this tag provides some new functionality which we could not have achieved by any other means but this tag makes it easier to filter out the lists on some specific parameters.
You can read more about this tag here. Also you can read about the Groovy GDK’s grep method usage here to see how and in what scenarios you can use this tag.
Hope this helps !!
- Abhishek Tejpaul
abhishek@intelligrape.com
Posts Tagged ‘ gsp ’
Grails GSP tag: grep
Getting started with jQuery Mobile
JQuery mobile provides set of features which are supported on almost all smartphones such as touch UI, ajax navigation, animated page transitions. Building jQuery mobile page is very simple, here’s how:
- A jQuery Mobile site must start with an HTML5 ‘doctype’ to take full advantage of all of the framework’s features.
- First of all you need jQuery, jQuery mobile, mobile theme stylesheets from CDN.
- Reference all styles & scripts in the head of page.
- A meta viewport tag in the head sets the screen width to the pixel width of the device.
- Inside body of html page a div with data-role of page is used as a wrapper for whole page.
- For header bar add a div with data-role of header.
- For content region add a div with a data-role of content & add content between this div.
- There are many features provided by jQuery mobile. Here i am explaining one of them which is list. For list, simply add ul tag with attribute data-role of listview between
. - To make it look like an inset module add an attribute data-inset=”true”.
- For dynamic search filter just add another attribute data-filter=”true”.
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Page Title</title> <link rel="stylesheet" href="css/jquery.mobile-1.1.1.css"/> <script src="js/jquery-1.8.0.min.js"></script> <script src="js/jquery.mobile-1.1.1.min.js"></script> </head>
<body>
<div data-role="page">
<div data-role="header">
Header
</div>
<div data-role="content">
<p>This is jquery mobile test page</p>
</div>
<div data-role="footer">
©intelligrape
</div>
</div>
</body>
<div data-role="content">
<ul data-role="listview" data-inset="true" data-filter="true">
<li>Blue</li>
<li>Black</li>
<li>Green</li>
<li>Yellow</li>
<li>White</li>
</ul>
</div>
Change user preferred locale using spring’s SessionLocaleResolver
Here we are going to talk about a scenario where there are some records in database which are specific to locale and they need to be displayed as per user’s current locale at number of places.Also user can change its preferred locale.
For this I preferred to set the user’s locale in the session object. There are two ways to do this :-
1. Add attribute “lang” to the request and it will be available to session automatically.
For example: whenever user clicks on the link, the language will change to English and the user will remain on the same page.
<g:link controller="${params.controller}" action="${params.action}" params="${params+[lang:'en']}">English</g:link>
/*Add different languages here*/
2.Also set default locale in the session in case, it is not set.
For that add following to any Filters :-
if (!session.'org.springframework.web.servlet.i18n.SessionLocaleResolver.LOCALE') {
LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
localeResolver.setLocale(request, response, new Locale('en'));
}
This sets the locale in spring’s SessionLocaleResolver class. Session always refer for the locale from here only.
Now one can check the locale wherever session is available. For example in GSPs:
<g:if test="${session.'org.springframework.web.servlet.i18n.SessionLocaleResolver.LOCALE'.toString()=='en'}">
Note: This implementation is useful to set locale in session (for accessing many times). Otherwise locale is available directly from current request as given below:-
import org.springframework.web.servlet.support.RequestContextUtils as RCU Locale locale=RCU.getLocale(request)
Hope this helped!
Nitesh Goel
[Intelligrape Software Pvt. Ltd.]
Using TagLib to avoid changes due to change in URLMappings
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.
Grails taglib and JavaScript file
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
Request Mocking to use groovyPagesTemplateEngine in backend threads
We have a setup where a backend thread, fired by the Spring Events, does some processing, generates a PDF and emails the result to the user.
The code we were using to generate the HTML from a GSP to be converted to a PDF using iText was as follows :
def webRequest = RequestContextHolder.getRequestAttributes()
def originalOut = webRequest.out
try {
def sw = new StringWriter()
def pw = new PrintWriter(sw)
webRequest.out = pw
groovyPagesTemplateEngine.createTemplate("path_to_gsp").make([model:model]).writeTo(pw)
return sw.toString()
} finally {
webRequest.out = originalOut
}
There was the obvious fallibility of this code that there was no Current Request associated with the backend thread!
After doing some googling around it, I came across a few threads and posts which talked about Request Mocking, which has been used in Grails Template Engine Plugin. We overcame this by using the code snippet given below to mock the web request
def webRequest = RequestContextHolder.getRequestAttributes()
if(!webRequest) {
def servletContext = ServletContextHolder.getServletContext()
def applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext)
webRequest = grails.util.GrailsWebUtil.bindMockWebRequest(applicationContext)
}
However, things didn’t end there. This code broke while working on a WAR environment. The problem was that the MockWebRequest class was part of the “org.springframework:org.springframework.test:3.0.3.RELEASE” jar and had to be included in the BuildConfig.groovy as
dependencies{
runtime 'org.springframework:org.springframework.test:3.0.3.RELEASE'
}
Ensure that the line
mavenCentral()
is not commented in BuildConfig.groovy
We were working on Grails 1.3.4
Hope this helps.
Vivek
http://in.linkedin.com/in/svivekkrishna
Grails way for rendering the GSP templates: The tmpl namespace.
Today while working on a project, I paired up with my colleague (Uday) and we found that we can render a gsp template in a different manner also. Grails provide us a “tmpl” namespace for rendering the GSP templates.
The old way that we use to render a gsp template
<g:render template="templateName" model="[books:books, authors:authors]"/>
The other way for rendering the template.
<tmpl:templateName books=${books} authors="${authors}"/>
Like me, you also must be wondering that if the template is in some other path like some shared folder “/shared/templateName” then how this <tmpl/> would work?
e.g.
<g:render template="/shared/templateName" model="[books:books, authors:authors]"/>
The answer is: <tmpl:/shared/templateName/>
<tmpl:/shared/templateName books=${books} authors="${authors}"/>
* you can find the documentation for this on http://www.grails.org/doc/latest/guide/single.html
Concerns, comments or suggestions are always welcome.
Cheers!!!!!
~Chandan Luthra~
chandan(aT)intelligrape(dOt)com
http://in.linkedin.com/in/luthrachandan/
Finding User’s Session Locale in GSP
There are situations where you might want to know the Locale of the user as set in the session in your GSP so that you can show text in a particular language/manner. Here the Spring framework’s SessionLocaleResolver can come to the rescue. In one of our recent Grails projects, we did the following in one of our GSPs to display the content accordingly.
Please note that our use-case was like that in which we have fields for different languages in our domain classes. For example:
class MyDomain { String greetingEnglish String greetingFrench }And now you have to conditionally display the object’s fields based on the user’s locale. If this were a static text, then the Grails in-built i18n support in the form of message bundles would be the ideal solution. But this is a different scenario.
So let’s start by writing the following in your GSP :
<g:set var="lang" value="${session.'org.springframework.web.servlet.i18n.SessionLocaleResolver.LOCALE'}"/>The above statement returns the ISO Language Code from the session object which is a map. In Grails, the map values can be retrieved by the ‘.’ operator too by passing the keys. These codes are the lower-case, two-letter codes as defined by ISO-639. For example: ‘en’ for English, ‘fr’ for French and so on.
Once you know the locale, you can show the conditional content on your page. It could be something like this:
<g:if test="${lang.startsWith('en')}"> <h1> ${myDomainobject.greetingEnglish} </h1> </g:if> <g:elseif test="${lang.startsWith('fr')}"> <h1> ${myDomainobject.greetingFrench}</h1> </g:elseif> <g:else> <h1> Default Greeting </h1> </g:else>Hope this will help !!!
- Abhishek Tejpaul
[Intelligrape Software Pvt. Ltd.]
Posted in Grails, HTML-UI-CSS

