Sherif
Sherif

Reputation: 431

Multiple values selection in <g:select> error

I'm trying to use multiple values for a select using <g:select multiple='true'>, but when i try to save the form to the DB, i got this error

Property [Languages] of class [class com.Myapp.hr.EmploymentSeeker] with value [french,english] is not contained within the list [[french, english, russian, chinese]]

here is my Domain:

class EmploymentSeeker {
 Set<String> languages = [] as Set
 static hasMany = [ languages: String ]
 static constraints = {
languages(nullable:true,inList:Holders.config.languages)
 }

}

Config file :

languages=[
'french',
'english',
'russian',
'chinese'
]

GSP:

<g:select  multiple="true" name="languages" from="${employmentSeekerInstance.constraints.languages.inList}" value="${employmentSeekerInstance?.languages}" valueMessagePrefix="empSeeker.languages" noSelection="['': '']"/>

what may cause this error ?

Upvotes: 1

Views: 502

Answers (1)

Taras Kohut
Taras Kohut

Reputation: 2555

As mentioned in Grails doc:

inList: Constrains a value so that it must be contained within the given list.

The problem is that your inList constrant it's a list of Strings, but languages from EmploymentSeeker isn't a String, it's a Set.

If it was a String, it would work, for example:
'french' is contained in ['french','english','russian','chinese']
But you have a Set, so
['french'] isn't contained in ['french','english','russian','chinese']

To make it work with inList you have to set in the constraint list all the combinations that user could choose, like:
[['french'], ['french', 'english'], ['english', 'french'] ...] and so on.
This answer describes how to archive those combinations, but actually it's not a good solution, because subsequences() doesn't care about permutations. However, adding permutations will increase your constraint list exponentially after growing of languages list.

As you can see, using inList is not a good solution in your case.

I would recomment to implement your custom simple constraint, like this:

languages(nullable:true,validator: {value, object ->
                Holders.config.languages.containsAll(value)​​​)​
        })

You can read about custom constraints here and here

Upvotes: 1

Related Questions