Monday, May 31, 2010

in-line editing in scaffolded show.gsp

In the default pages created by the scaffolding mechanism of grails, it is quite cumbersome that whenever you want to change a value of a domain class you have to go to the edit page and afterwards back to the show page. Two complete site loads that do not fit into the web 2.0 paradigm.

Usually one would apply in-line editing to bring in a cool and useful AJAX feature and in fact every JS library seems to have built-in support. It is however quite labourous if you have to add this feature manually to every field even if you make things easier with a tag lib as suggested in the book "Beginning Groovy and Grails" by Christopher M. Judd, Joseph Faisal Nusairat and James Shingler.

I thought about the problem and then decided to try to combine scaffolding with this technique. I used the example from the book as a guideline.

I changed the following entry within show.gsp:

<td valign="top" class="value">\${fieldValue(bean: ${propertyName}, field: "${p.name}")}</td>

to:
<td>
 <g:editInPlace 
  id="${p.name}"       
  url="[action: 'editField', id:${propertyName}.id]"
  rows="1"
  cols="10"
  paramName="${p.name}">\${fieldValue(bean: ${propertyName}, field: "${p.name}")}
 </g:editInPlace>
</td>

One can use the TagLib given by the book, but you have to modify the action in order to work with arbitrary fields. Add the following method to the scaffolded Controller.groovy (/src/templates/scaffolding):

def editField = {
  // Retrieve member
  def ${propertyName} = ${className}.get(params.id)
  if(${propertyName})
      {
      ${propertyName}.properties = params
      ${propertyName}.save()
      // Render a new page.
      render params.get(params.editorId)
  }
    }

Thursday, May 27, 2010

Microsoft SQL Server 2005 with GRAILS

Today I found a blog that helped me setting up MS SQL 2005 Express with Grails in a few minutes.

http://lsonline.de/blog/2009/11/grails-with-microsoft-sql-2005/

Sunday, May 16, 2010

Use grailsui Menubar in taglib

The common way of using the grailsui menubar is to incorporate the offered tags like or directly into a template. For my purposes, where I wanted to create a menu based on database properties, I wanted to build a menubar within my own taglib. Although tags can be easily accessed like for example g.createLink(), I had to study the source code of MenuTagLib.groovy to find out what parameters were expected of me. The example shows how it works:

out << gui.menubar(id: 'topMenuBar', renderTo:'top1'){ gui.submenu(label: 'Links'){ gui.submenu(label: 'Search'){ gui.menuitem(url:'http://www.google.de', helpText: 'Google'){ 'Google' } } } }


Here is what caused me some problems: You have to define the parameter helpText (can also be ''). A url is needed, to trigger some controller action you can use createLink. Still have to figure out how to use remoteLink here. The label of the menuitem is not a parameter, but the body of the menuitem {}.

And a last remark: As the menubar did not work properly with my yui layout manager, I had to change two things. First I had to add the parameters zIndex:1 and scroll:null to the layout definition:

{ position: 'top', height: 24, body: 'top1', zIndex: 1, scroll: null },

zIndex tells the layout manager which element overlaps and the default is 0. As this is my onley zIndex higher than 0, the menu will overlap all other parts. Furthermore, scroll: null enables the menu to escape the borders of the div container.

I mentioned a second thing to change: Only if you add the parameter renderTo: 'top1' to the menubar definition, the menubar becomes active.

Friday, May 14, 2010

RichUI TreeView onLabelClick does not work with current YUI

Running into this problem again and again, I decided to finally write down what one has to change in order to make the onLabelClick work again:

The root of the problem is that in the current YUI the name of the action has changed. This is why you have to open the TreeViewRenderer.groovy in the src folder of the RichUI Plugin.

There you have to look for line 36 and switch "labelClick" with "clickEvent". VoilĂ .

Just a remark: If you want to access the id of the node late - please don't ask why - access node.node.additionalId in contrary to node.id or node.additionalId. Further change that line 37 accordingly.

Thursday, May 6, 2010

YUI layout manager



Yesterday I discovered the YUI layout manager. It is a javascript solutions dividing your browser viewport into up to 5 parts (top, bottom, left, right and center). If you ask, why should I use that thing and not rely on div/css. Here are some advantages I can immediately see here:
  1. It is super easy to produce the basic layout you like in <>
  2. You get cool js effects like resizing, toggling, etc.
  3. You can be sure that the layout works in every browser (YUI is reliable in this).
  4. It looks super cool and is skinnable via CSS.
Here is what you have to do:

Include the following resources:
<script type="text/javascript" src="http://yui.yahooapis.com/combo?2.8.0r4/build/utilities/utilities.js&2.8.0r4/build/container/container-min.js&2.8.0r4/build/resize/resize-min.js&2.8.0r4/build/layout/layout-min.js&2.8.0r4/build/menu/menu-min.js"/>
Include the following script:
<script type="text/javascript">
YAHOO.util.Event.onDOMReady(function() {
var layout = new YAHOO.widget.Layout({
units: [
{ position: 'top', height: 28, body: 'top1' },
{ position: 'right', header: 'Right', width: 300, resize: false, collapse: true, scroll: true, body: 'right1', animate: true, gutter: '5' },
{ position: 'bottom', height: 28, body: 'bottom1' },
{ position: 'left', header: 'Left', width: 200, body: 'left1', gutter: '5', resize: true, scroll: true, animate:true, collapse:true},
{ position: 'center', body: 'center1', gutter: '5 0', scroll: true }
]
});

layout.render();
});
</script>
The options are self-explaining and make the whole thing easy to configure. You can even nest layouts like in the attached screenshot.

Wednesday, May 5, 2010

access templates belonging to plugins - file not found exception

My current web project is split up into several parts. The best way to achieve this was utilizing the plugin mechanism of grails. Unfortunately grails (1.2 SNAPSHOT) is not able to find templates that are part of a plugin. I am quite sure I installed the plugins properly, as controllers, etc. are found.

Apparently, this is a known bug and lucky for me there is also a work-around presented:

render(template:"/bla/foo", plugin:"name-of-plugin", ...) and for gsp <g:render template="/bla/foo" plugin="name-of-plugin" ... />


Works perfectly as soon as you find out what the correct sPelLinG of your plugin is. In the end I used "grails list-plugins" to answer that question.

changing the style of yui treeview



In my project I make use of the YUI-TreeView widget. The CSS files of YUI are - let's say overwhelming. I found a nice description of how to find the correct style classes with Firebug. Here is an example where the developers explain how to obtain a folder style tree view.

I really just wanted to perform a small little change: The focus bg color of the selected tree nodes. This is what you have to override in your CSS:

.ygtvfocus{background-color:#B4CCFF;}

Tuesday, May 4, 2010

passing javascript parameters with remoteFunction

There have been a lot of examples where I needed to pass javascript variables through a remoteFunction in order to Ajax-Update a part of my web application.

I had almost given up when I found the solution in a blog entry. I wasn't able to guess the correct escaping of ' signs on my own, but this solution obviously got it right:

${remoteFunction(controller:'myController',
action:'someAction',update:'targetDiv',
params:'\'oneParameter=\'+jsOneParameter+\'&anotherParameter=\'+jsSecondParameter')};

service dependency injection does not work in scaffolded controllers

When I wanted to access user information in the scaffolding code of the controller (/src/scaffolding/Controller.groovy) my first guess was to define the authenticateService and let dependency injection do the trick. Unfortunately, this approach did not work.

def authenticateService is never injected and therfore a useless null object.

I spent some time on google and it turned out that this is an open issue and that others had stumbled about the same problem. I was happy to see that someone had found a workaround:

def authenticateService = org.codehaus.groovy.grails.commons.ApplicationHolder.application.mainContext.getBean("authenticateService")


Using this approach arbitrary services can be injected into the scaffolded controllers.

session.user does not work with grails acegi plugin

Most tutorials and books introducing grails security concepts tell us that you can access information concerning the user by accessing the session.user object.

As I installed the acegi security plugin to get more advanced security features, this approach didn't work anymore. The documentation provided the solution.

If you are operating on GSPs you can use:

${loggedInUserInfo(field:'userRealName')}, which tells you the real name of the user. The field 'username' would provide you with the login name.

There are also the tags ${isLoggedIn} and ${isNotLoggedIn} to ensure that some content is only available to authenticated users.

But what happens if you want to access this information within a taglib or a controller? You have to include the authenticateService and use it:

Use authenticateService.isLoggedIn() to find out, whether a user is logged in, or not.

And use the following to access the user credentials:
def principal = authenticateService.principal()
println principal.getUsername()//get username
println principal.getAuthorities()//get authorities

Keep attention: If you want to obtain the User object you can no longer search for 'login', but for 'username':

User.findByUsername(principal.getUsername());

Monday, May 3, 2010

missing js files (bubbling library)

As javascript is not entirely my mother tongue, I am using the wonderful GrailsUI plugin to bring some magic to my web project. The plugin itself is making heavy use of the YUI library and the bubbling extension. Therefore, it needs the respective js files in the web-app/js directory.

Today, I messed up my plugin configuration (Subclipse decided to ruin my day) . As a consequence I reinstalled all plugins,. I was quite unhappy with the result, as the GSPs just ignored all the components. Using Firebug, I found out that the js files of bubbling were all missing.

It turned out that the files that were expected to be in the subfolder web-app/js/yui-cms/2-1 were actually in 2.1. Renaming the folder solved that problem.

sharing my thoughts

Hi folks,

just a few words about this blog:

I started developing a new grails application a few weeks ago, and although grails is a great technology that made a lot of things easier for me, there have been a lot of problems I ran into. I could however solve most of them up until now. Most of the solutions I had found with the help of google and often they were blog entries. So I thought I could start to give some of my own solutions or solutions I found on the web, back to the community. The main purpose however, is to remind myself how I had solved a particular problem, so please be forgiving if I am cheap on examples.