I created a new Grails 2.5.1 project with 2 domains, and used generate-all to create the scaffolding. One of the domains hasMany of the other domain: User hasMany roles. When I run the app and create a new user and select a role for the user, it adds it. I can add multiple roles for a user, or remove them, except for the last one. I can't remove the last one. If I try to remove all the roles for a user it ignores it and leaves the roles that were selected previously. (I found the same behavior in Grails 2.4.4.)
Domains:
class Role {
String name
}
class User {
String name
static hasMany = [roles: Role]
}
The scaffolding view creates the html select box with:
<g:select name="roles" from="${myapp.Role.list()}"
multiple="multiple" optionKey="id" size="5"
value="${userInstance?.roles*.id}" class="many-to-many"/>
Creating this html:
<select id="roles" class="many-to-many" size="5" multiple="multiple" name="roles">
<option selected="selected" value="1">myapp.Role : 1</option>
<option value="2">myapp.Role : 2</option>
</select>
To reproduce:
I understand that nothing is submitted with the form for that field if nothing is selected. I can fix it by doing user.roles.clear()
before binding. That works, but I'm wondering...
Is the scaffolding really not designed to handle this case? Or, am I doing something wrong, like in the way my domains are coded? Is there a better solution than editing the scaffolding to clear the roles before binding?
I am not sure how do you unselect the roles as there will be at least one role selected on the form always while editing if you had added a role during creation.
You would have to change scaffolded views to achieve what you want. Use noSelection property of g:select to specify what should be the default value if user doesn't want to select any existing role.
Your g:select tag then would be:
<g:select name="roles" from="${myapp.Role.list()}"
noSelection="['': '--NoSelection--']"
multiple="multiple" optionKey="id" size="5"
value="${userInstance?.roles*.id}" class="many-to-many"/>
And Scaffolding lets you generate some basic CRUD interfaces for a domain class. It doesn't support a lot of things ans you have to implement them on your own.