views:

219

answers:

2

My main question here is dealing with the pramas map when having a one-to-many relationship managed within one dynamic form, as well as best practices for dealing with one-to-many when editing/updating a domain object through the dynamic form. The inputs for my questions are as follows.

I have managed to hack away a form that allows me to create the domain objects shown below in one Dynamic form, since there is no point in having a separate form for creating phone numbers and then assigning them to a contact, it makes sense to just create everything in one form in my application. I managed to implement something similar to what I have asked in my Previous Question (thanks for the people who helped out)

class Contact{

    String firstName
    String lastName
    // ....
    // some other properties
    // ...

    static hasMany = [phones:Phone]
    static mapping = {
        phones sort:"index", cascade: "all-delete-orphan"
    }
}

class Phone{
    int index
    String number
    String type
    Contact contact

    static belongsTo = [contact:Contact]
}

I basically managed to get the values from the 'params' map and parse them on my own and create the domain object and association manually. I.e. i did not use the same logic that is used in the default scaffolding, i.e.

Contact c = new Contact(params)

etc...., i just looped through all the params and hand crafted my domain objects and saved them and everything works out fine.

My controller has code blocks that look like this (this is stripped down, just to show a point)

//create the contact by handpicking params values
def cntct = new Contact()
cntct.firstName = params.firstName
cntct.lastName = params.lastName
//etc...

//get array of values for number,type
def numbers = params['phone.number']
def types =  params['phone.type']

//loop through one of the arrays and create the phones
numbers.eachWithIndex(){ num, i ->
    //create the phone domain object from 
    def phone = new Phone()
    phone.number = num
    phone.type = types[i]
    phone.index = i
    cntct.addToPhones(phone)
}

//save

My questions are as follows:

  • What is the best practice of handeling such a situation, would using Command objects work in this case, if yes where can i found more info about this, all the examples I have found during my search deal with one-to-one relationships, I couldn't find an example for one-to-many?
  • What is the best way to deal with the relatiohsips of the phones in this case, in terms of add/removing phones when editing the contact object. I mean the creation logic is simple since I have to always create new phones on save, but when dealing with updating a contact, the user might have removed a phone and/or editing an exiting one and/or added some new phones. Right now what I do is just delete all the phones a contact has and re-create them according to what was posted by the form, but I feel that's not the best way to do it, I also don't think looping over the existing ones and comparing with the posted values and doing a manual diff is the best way to do it either, is there a best practice on how to deal with this?

Thanks, hopefully the questions are clear.

[edit] Just for more information, phone information can be added and deleted dynamically using javascript (jquery) within the form [/edit]

+1  A: 

disclaimer: i do not know if the following approach works when using grails. Let me know later.

See better way for dynamic forms. The author says:

To add LineItems I have some js that calculates the new index and adds that to the DOM. When deleting a LineItem i have to renumber all the indexes and it is what i would like to avoid

So what i do

I have a variable which stores the next index

var nextIndex = 0;

When the page is loaded, i perform a JavaScript function which calculates how many child The collection has and configure nextIndex variable. You can use JQuery or YUI, feel free.

Adding a child statically

I create a variable which store the template (Notice {index})

var child   = "<div>"
           +=     "<div>"
           +=         "<label>Name</label>"
           +=         "<input type="text" name=\"childList[{index}].name\"/>"
           +=     "</div>"
           += "</div>"

When the user click on the Add child button, i replace {index} - by using regex - by the value stored in the nextIndex variable and increment by one. Then i add to the DOM

See also Add and Remove HTML elements dynamically with Javascript

Adding a child dinamically

Here you can see The Paolo Bergantino solution

By removing

But i think it is the issue grow up when deleting. No matter how many child you remove, does not touch on the nextIndex variable. See here

/**
  * var nextIndex = 3;
  */

<input type="text" name="childList[0].name"/>
<input type="text" name="childList[1].name"/> // It will be removed
<input type="text" name="childList[2].name"/>

Suppose i remove childList1 What i do ??? Should i renumber all the indexes ???

On the server side i use AutoPopulatingList. Because childList1 has been removed, AutoPopulatingList handles it as null. So on the initialization i do

List<Child> childList = new AutoPopulatingList(new ElementFactory() {
   public Object createElement(int index) throws ElementInstantiationException {
       /**
         * remove any null value added
         */    
       childList.removeAll(Collections.singletonList(null));

       return new Child();
   }
});

This way, my collection just contains two child (without any null value) and i do not need to renumber all the indexes on the client side

About adding/removing you can see this link where i show a scenario wich can gives you some insight.

See also Grails UI plugin

Arthur Ronald F D Garcia
+1  A: 

Thanks,

Your answer brought some insight for me to do a wider search and I actually found a great post that covers all the inputs in my question. This is just a reference for anyone reading this. I will write a blog entry on how I implemented my case soon, but this link should provide a good source of ino with a working exmaple.

http://www.2paths.com/2009/10/01/one-to-many-relationships-in-grails-forms/

omarello
@omarello Thank you for sharing your search. really good! (+1)
Arthur Ronald F D Garcia
I've posted a guide on how I did my phone book example, it's heavily based on the above post. Hope it will be helpful.http://omarello.com/2010/08/grails-one-to-many-dynamic-forms/
omarello
@omarello Now Thank you for sharing your knowledge. I will try it by using AutoPopulatingList. Just for curiosity: does Grails fullfil your needs well ???
Arthur Ronald F D Garcia
Well i'm still in the learning/experimenting stage, but I find it really convenient so far, I'm in the process of building a bigger test app and see how things go, I'll be writing about my experience as I go a long.
omarello