Replacement Form Item For Grails to-Many Relationships

By default, grails just gives users a multi-select box when dealing with to-Many relationships in views. It’s damn ugly and incredibly ineffective if an end user is dealing with tons of things to select from. After tolerating it for a while I completely gave up and decided to write my own replacement for it using autocomplete from the richui plugin and prototype which is included with grails.

So, the first thing you’re going to want to do is install the richui plugin, you can do this by running:

grails install-plugin richui

In the directory of your project.

Now, for the example that I’m going to use, there are two classes, Author and Book, an author hasMany Books. So that’s what we’re going to work with. I wrote a little TagLib that you can use, so I’m not going to explain that code, but I’ll show it to you below.

So basically, you need to write a controller for the autoComplete which you can find here, and you use my tag lib, below:

 def richMany = { attrs ->
    def name = attrs['name']
    def action = attrs['action']
    def many
    if(attrs['many'])
        many = attrs['many']
    else
        many = name
    def already = attrs['already']
    def params = attrs['params']
    def textField = attrs['textField']
 
    out << richui.autoComplete(name: "${many}AutoComplete", action: action, onItemSelect: "addAutoItem(\$('${many}AutoComplete').value, id)")
    out << """
            <script type="text/javascript"><!--mce:0--></script>
<div id="autoItemDiv">
"""
 
    already.each() { item -&gt;
        out << """
<div id="itemDiv${item.id}">
                        ${item.getProperty(textField)}
<input name="${name}" type="hidden" value="${item.id}" /><a onclick="removeAutoItem(${item.id})" href="#">(remove)</a></div>
"""
    }
    out <<  "</div>
"
}

Now, the way you call this is in your code, you have a tag like this:

<namespace:richMany name="members" action="autoCompleteListAccounts" already="${projectInstance.members}" params="id=${projectInstance.id}" textField="login" />

What this does is creates a richer version of the many multi-select, so rather than looking like a boring select box, it looks like this:
Screenshot
Another Screenshot
The way you configure this is through the parameters below:

  • name – This is the name of the data that has to be submitter, just copy the name of the select that was previously there.
  • action – This is the action for the autoComplete, it should return xml results with name and id.
  • already – These are the elements already belonging to the class, for example if you have a Author that hasMany [books : Book], this would be ${author.books}
  • params – these are the params you want to send to the autocomplete controller in the form of param1=val&param2=val etc.
  • testField – this is the property of the class which you pass to already (eg. book) that will show next to the words (remove) eg. “title” will result in text fetched from book.title

Also, make sure at the top of the page where you use this, you use the tag: “” of some sort for the richui to load the autocomplete javascript and for grails to load prototype.

And that’s all there is to it. Any questions, or anything you’d like me to elaborate on, just leave a comment.

Related posts:

  1. Introducing Grails – A Framework That Will Blow Your Mind
  2. The Basics of A WordPress Plugin
  3. Hello World WordPress Plugin
  4. grails generate-all: No domain class found Fix
  5. Grails + Mysql Connection Refused Error Help (Slackware or maybe not)

About hkothari

I am software developer and enthusiast. I enjoy trying out new software, but prefer to use light and easy to use software. I’m currently still in high school, but working my way through it. I intern in a college computer science department, using flex and java, but I prefer C/C++, PHP and Lua. I enjoy running and swimming too. I’m a devout slackware user, but I try out a ton of other linux distros for fun and in order to learn more.
This entry was posted in Howto/Tutorial, Programming, Scripts and tagged , , , , , , , . Bookmark the permalink.

Comments are closed.

blog comments powered by Disqus