简体   繁体   中英

Grails select tag results

I'm trying to update a hasMany relationship through a form using data binding, but the data I get in my params doesn't seem correct.

Domain class:

class CustomerSite {

static hasMany = [dhrs:DeviceHistoryRecord];

static mapping = {
    id generator:'sequence', params:[sequence:'cs_seq']
}
    ...
}

Edit view:

...
<g:select name="dhrs" id="dhrs" 
from="${DeviceHistoryRecord.list()}"
multiple="multiple"
optionKey="id"
value="${customerSiteInstance?.dhrs}"/>

Controller:

def update = {
    def customerSiteInstance = CustomerSite.get( params.id )
    if(customerSiteInstance) {

        customerSiteInstance.properties = params

        String flashMsg = new String();

        flash.message = "";

        if(!customerSiteInstance.hasErrors() && customerSiteInstance.save()) {
            flash.message += "Customer Site ${customerSiteInstance.toString()} updated"
            redirect(action:show,id:customerSiteInstance.id)
        }
        else {
            flash.message = flashMsg
            render(view:'edit',model:[customerSiteInstance:customerSiteInstance])
        }
    }
    else {
        flash.message = "Customer Site not found with id ${params.id}"
        redirect(action:edit,id:params.id)
    }
}

This gives me an error:

Error 200: org.springframework.beans.NotReadablePropertyException: Invalid property 'currentDeviceData' of bean class [java.lang.String]: Bean property 'currentDeviceData' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?

at this line in the controller code:

if(!customerSiteInstance.hasErrors() && customerSiteInstance.save()) {

That doesn't make any sense to me, but I did some fooling with it (a lot, actually), and eventually figured out that the g:select is passing in a collection of indexes to params.

The view outputs code that I think looks correct:

<select name="dhrs" id="dhrs" multiple="multiple" >
  <option value="2421" >801122</option>
  <option value="2422" >801123</option>
  ...

If I were to select items at index 0 and index 1 of the list, it's not passing in a set of "2421" & "2422" like I'd expect. It's passing in "0" & "1". To make matters worse, after I run that, when I go back to the edit page and run it again, this time selecting something at index 8, it's going to have "8"...but also the "0" and "1" from last time.

Looking around here a bit, I found Selecting multiple values from select tag - Grails , which has some other ideas, including making a change like this:

<g:select name="dhrs.id" 
  from="${DeviceHistoryRecord.list()}" 
  multiple="multiple" 
  optionKey="id" 
  value="${customerSiteInstance?.dhrs*.id}"/>

But that gave me a missing method error, although it did fix the issue of having indexes instead of actual values returned.

Any ideas of what's going on here and how I can fix it?

BTW, I'm running version 1.0.4 of Grails. Yes, I'd love to upgrade it, but I can't.

Thanks!

I spent more time on this, and got a partial solution. Here's what I ended up with:

<g:select name="dhrsX.id" 
          from="${DeviceHistoryRecord.list()}"
          multiple="multiple"
          optionKey="id"
          value="${customerSiteInstance?.dhrs*.id}"/>

Notice that's dhrsX - not dhrs . That way, I can manually lookup each one before setting them in the CustomerSite object. The only complication is that if the user selects one item, dhrsX contains a String ; if the user selects multiple items, dhrsX contains a list of String s. To address that, I needed to repackage the selection results before trying to use them directly.

def update = {
    def customerSiteInstance = CustomerSite.get( params.id )
    if(customerSiteInstance) {

        customerSiteInstance.properties = params
        customerSiteInstance.dhrs.clear()

        for(thisDHR in params.dhrsX) {
            def value = thisDHR.getValue()
            def ArrayList<String> list = new ArrayList<String>();
            if (value instanceof String) {
                list.add(value)
            } else {
                for(oneValue in value) {
                    list.add(oneValue)
                }
            }

            for(aDHR in list){
                DeviceHistoryRecord rec = DeviceHistoryRecord.get(aDHR)
                if (rec != null) {
                    customerSiteInstance.addToDhrs(rec)
                } else {
                    print(thisDHR + " NOT FOUND!")
                }
            }
        }
...

Now single selection and multiple selection work...but there's still a small outstanding issue. Despite calling clear() on dhrs before adding the new selections, the prior selections remain. I don't expect this to be nearly as complicated to fix, however.

In the g:select use:

value="${customerSiteInstance?.dhrs?.id}"

Questionmark instead of star. This is how I have my "multiselects".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM