Bulba
Bulba

Reputation: 835

grails: how to properly edit/update a collection?

I just wasted half a day trying to figure this out, reading about some workarounds, and thinking "it can't be that bad - there must be a straightforward to do edit a collection in Grails, whethere using scaffolded views or my own."

Let's say I have this domain object:

class TreeGroup {
    String name
    List<Tree> trees      

    static hasMany = ['trees': MyTree]
}

Just to explain the choice of data structure - I need my records to be unique, but in the order I set. That's why I chose List, AFAIK one cannot rely on order in a Set. So there are 2 pieces to this question - 1) how to remove from any Collection, for example a Set, 2) is List the best replacement for Set in this context (preserving order).

I want to be able to create a group record with no trees in it and make 4 updates:

And obviously, I want the desired state after every step. Currently though, I can only add records, and if I even edit/save to list, the list elements are added to it again.

I am using the multiple select tag for this. It looks like this:

<g:select name="trees" from="${allTrees}" optionKey="id" 
          multiple="true" class="many-to-many"
          value="${trees ? trees*.id : treeGroupInstance?.trees*.id}" />

and that's fine, in the sense that it generates an HTTP header with these variables on update:

_method:PUT
version:19
name:d5
trees:1
_action_update:Update

But the data binder only adds new elements, it never lets you edit a list.

What is the cleanest way to do it ? Is it me, not reading something obvious, or is this a design flaw of grails data binding (and of so, when/how will it be fixed) ?

Is there a way perhaps via a hidden HTTP parameter to clear the list before (re)adding elements ?

Thanks

Upvotes: 0

Views: 497

Answers (1)

Bulba
Bulba

Reputation: 835

I ended up doing this:

private repopulate(def domainObject, String propertyName, Class domainKlaz) {
    if (params[propertyName] != null) {
        domainObject[propertyName].clear()
        domainObject[propertyName].addAll(
              params[propertyName].collect { domainKlaz.get(it) }
        )
    }
}

and I am calling it in update controller method before save(), for every collection. OMG how ugly.

Upvotes: 1

Related Questions