Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Passing params.id to globalFilterClosure #106

Closed
kendoig opened this issue Jul 23, 2014 · 19 comments
Closed

Passing params.id to globalFilterClosure #106

kendoig opened this issue Jul 23, 2014 · 19 comments

Comments

@kendoig
Copy link
Contributor

kendoig commented Jul 23, 2014

I have just upgraded from EasyGrid 1.4.3 to 1.6.3 and have noticed that a previously working globalFilterClosure no longer works as expected. I used to happily read the value of params.id and use it like so:

globalFilterClosure
        {
            params ->
                seqSample { eq( 'id', params.id ? params.id as long : -1l ) }
        }

This was evaluated at runtime and I got the correct rows. After upgrading, the params.id value is correct in the controller but not passed through to the closure. Is the closure not evaluated at runtime any longer or am I not understanding how its meant to work. BTW the params.id value is a key to a related table to the one in the grid.

Thanks for any assistance
Ken Doig

@ericraskin
Copy link

I believe I have the same issue with a subGrid. I see that the ID parameter is not being passed to the subGrid.

The main grid has:

        dataSourceType 'gorm'
        domainClass PASOrder
        idColName 'ordnum'
        subGrid 'ownerListOrderDetails'

The subGrid has:

        dataSourceType 'gorm'
        domainClass Ordline
        globalFilterClosure{ params ->
            rentalOrder {
                eq ('ordnum', params.id ? params.id as long: -1l)
            }
        }

I put a breakpoint at GormDataSourceService:184 (the list() function) and watched it operate. The listParams contains "{rowOffset=0, maxRows=10}". There is no ID field in there for the globalFilterClosure to access.

@tudor-malene
Copy link
Owner

'params' should be accessible directly, without any argument.
Try this:

globalFilterClosure
        {            
                seqSample { eq( 'id', params.id ? params.id as long : -1l ) }
        }

or

globalFilterClosure{ 
            rentalOrder {
                eq ('ordnum', params.id ? params.id as long: -1l)
            }
        }

@kendoig
Copy link
Contributor Author

kendoig commented Jul 25, 2014

Yes params is accessible but it doesn't have the id attribute which I can see in the controller action:

    def svlist()
    {
        println("In svList(${session.user}): Params = ${params}")
        return  [seqSample: SeqSample.get( params.id )]
    }

and here is the globalFilterClosure:

        globalFilterClosure
        {
            println( "In gfc: ${params}")
            seqSample { eq( 'id', params.id ) }
        }

This is the output I see:

In svList(Ken Doig): Params = [id:16531, action:svlist, controller:seqVariant]
2014-07-25 11:27:26,990 [http-bio-8080-exec-1] WARN  easygrid.EasygridDispatchService  - No service method for: callGridImplHtmlGridDefinition
In gfc: [sord:asc, page:1, nd:1406251647149, sidx:, rows:20, _search:false, action:curationRows, controller:seqVariant]
In gfc: [sord:asc, page:1, nd:1406251647149, sidx:, rows:20, _search:false, action:curationRows, controller:seqVariant]

But no records are returned.

@kendoig kendoig closed this as completed Jul 25, 2014
@kendoig kendoig reopened this Jul 25, 2014
@tudor-malene
Copy link
Owner

You will have to use the externalParams attribute of GridConfig.

def yourGrid={
....
    externalParams = ['id']
...
}

By default it's empty. It represents the list of parameters which the grid can use from the enclosing page.

@ericraskin
Copy link

That's new? It worked before I upgraded. Does this go in the main grid or the subgrid?

I tried putting externalParams ['id'] in the subGrid and I got this:

| Error 2014-07-25 09:53:24,208 [localhost-startStop-1] ERROR context.GrailsContextLoaderListener  - Error initializing the application: Cannot get property 'id' on null object
Message: Cannot get property 'id' on null object
    Line | Method
->>  671 | doCall                      in pasweb.CustomerAccessController$_closure7
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|    176 | buildWithDelegate           in org.grails.plugin.easygrid.builder.EasygridBuilder
|     49 | evaluateGrid . . . . . . .  in     ''
|    193 | initializeFromClosureMethod in org.grails.plugin.easygrid.EasygridInitService
|    183 | doCall . . . . . . . . . .  in org.grails.plugin.easygrid.EasygridInitService$_initControllerGrids_closure12
|    181 | initControllerGrids         in org.grails.plugin.easygrid.EasygridInitService
|     50 | doCall . . . . . . . . . .  in org.grails.plugin.easygrid.EasygridInitService$_initializeGrids_closure2
|     49 | initializeGrids             in org.grails.plugin.easygrid.EasygridInitService
|     61 | doCall . . . . . . . . . .  in EasygridGrailsPlugin$_closure4
|    262 | run                         in java.util.concurrent.FutureTask
|   1145 | runWorker . . . . . . . . . in java.util.concurrent.ThreadPoolExecutor
|    615 | run                         in java.util.concurrent.ThreadPoolExecutor$Worker
^    745 | run . . . . . . . . . . . . in java.lang.Thread

Here is the entire definition for the master and subGrid, in case it helps. As I said -- this worked fine before I upgraded to 1.6.3:

    def ownerListOrdersGrid = {
        dataSourceType 'gorm'
        domainClass PASOrder
        idColName 'ordnum'
        subGrid 'ownerListOrderDetails'
        globalFilterClosure{ params ->
            rentalList {
                eq('id', params.listId ? params.listId as long: -1l)
            }
        }
        initialCriteria {
            eq('ord_type','LRO')
            eq ('cancelled','1')
        }
        enableFilter true
        inlineEdit false
        jqGrid {
            sortname 'orddate'
            sortorder 'desc'
            rowNum 50
        }
        columns {
            ordnum {
                type 'id'
                label "PAS Num"
                jqgrid {
                    width "75"
                    align "center"
                }
            }
            mgrnum {
                label "Mgr Num"
                jqgrid {
                    width "100"
                    align "center"
                }
            }
            bkrnum {
                label "Broker PO"
                jqgrid {
                    width "100"
                    align "center"
                }
            }
            mailer {
                label "Mailer"
                value { it.rentalMailer.company }
                sortProperty "rentalMailer.company"
                jqgrid {
                    width "175"
                }
            }
            orddate {
                label "Order Date"
                jqgrid {
                    width "100"
                    align "center"
                }
            }
            maildate {
                label "Mail Date"
                jqgrid {
                    width "100"
                    align "center"
                }
            }
            wantdate {
                label "Want Date"
                jqgrid {
                    width "100"
                    align "center"
                }
            }
            shipdate {
                label "Ship Date"
                jqgrid {
                    width "100"
                    align "center"
                }
            }
            statusDesc {
                label "Status"
                jqgrid {
                    width "100"
                    align "center"
                }
            }
            decoy {
                label "Decoy String"
                jqgrid {
                    width "100"
                    align "center"
                }
            }
        }
    }

    def ownerListOrderDetailsGrid = {
        dataSourceType 'gorm'
        domainClass Ordline
        globalFilterClosure{ params ->
            rentalOrder {
                eq ('ordnum', params.id ? params.id as long: -1l)
            }
        }
        initialCriteria {
            'in'('nthflag',['1','2','3'])
        }
        jqgrid {
            sortname 'linenum'
            sortorder 'asc'
        }
        enableFilter false
        inlineEdit false
        jqgrid {
            height '100%'
        }
        columns {
            keycode {
                label "Keycode"
                jqgrid {
                    width "100"
                }
            }
            segment {
                label "Segment"
                jqgrid {
                    width "150"
                }
            }
            ordqty {
                label "Order Qty"
                jqgrid {
                    width "100"
                    align "right"
                    formatoptions: {defaultValue: ''}
                }
            }
            shipqty {
                label "Ship Qty"
                jqgrid {
                    width "100"
                    align "right"
                    formatoptions: {defaultValue: ''}
                }
            }
        }
    }

I also tried removing the "params ->" from the globalFilterClosure in the subGrid, but that made no difference either. The subGrid is still empty even though I know it contains data.

@tudor-malene
Copy link
Owner

Yes, externalParams is new and should have worked properly
It's a bug indeed.
I'll solve this during this weekend.

@ericraskin
Copy link

Thanks. Going on vacation for a while. Will revisit in mid-August when
I get back. :-)

On 07/25/2014 02:15 PM, Tudor Malene wrote:

Yes, externalParams is new and should have worked properly
It's a bug indeed.
I'll solve this during this weekend.


Reply to this email directly or view it on GitHub
#106 (comment).


Eric H. Raskin 914-765-0500 x120
Professional Advertising Systems Inc. 914-765-0503 fax
200 Business Park Dr Suite 304 eraskin@paslists.com
Armonk, NY 10504 http://www.paslists.com

@tudor-malene
Copy link
Owner

Have fun!

@kendoig
Copy link
Contributor Author

kendoig commented Jul 28, 2014

No luck with

        externalParams = ['id']
        globalFilterClosure
        {
            if ( params.id =~ /\d+/ )
            {
                long id = params.id as long
                println( "In gfc: ${params} id=${id}")
                seqSample { eq( 'id', id ) }
            }

            order( 'reportable', 'desc' )
            order( 'curated',    'desc' )
        }

as discussed.

Compile errors:

| Error 2014-07-28 14:39:23,807 [localhost-startStop-1] ERROR context.GrailsContextLoader  - Error initializing the application: No such field: externalParams for class: org.grails.plugin.easygrid.builder.EasygridBuilder
Message: No such field: externalParams for class: org.grails.plugin.easygrid.builder.EasygridBuilder
   Line | Method
->> 268 | doCall                      in org.petermac.pathos.curate.SeqVariantController$_closure2
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|   176 | buildWithDelegate           in org.grails.plugin.easygrid.builder.EasygridBuilder
|    49 | evaluateGrid . . . . . . .  in     ''
|   193 | initializeFromClosureMethod in org.grails.plugin.easygrid.EasygridInitService
|   183 | doCall . . . . . . . . . .  in org.grails.plugin.easygrid.EasygridInitService$_initControllerGrids_closure12
|   181 | initControllerGrids         in org.grails.plugin.easygrid.EasygridInitService
|    50 | doCall . . . . . . . . . .  in org.grails.plugin.easygrid.EasygridInitService$_initializeGrids_closure2
|    49 | initializeGrids             in org.grails.plugin.easygrid.EasygridInitService
|    61 | doCall . . . . . . . . . .  in EasygridGrailsPlugin$_closure4
|   303 | innerRun                    in java.util.concurrent.FutureTask$Sync
|   138 | run . . . . . . . . . . . . in java.util.concurrent.FutureTask
|   895 | runTask                     in java.util.concurrent.ThreadPoolExecutor$Worker
|   918 | run . . . . . . . . . . . . in     ''
^   695 | run                         in java.lang.Thread

My current work around it to change GridUtils.groovy to

    static def externalParams(gridConfig) {
        println( "in externalParams ${params} [${params.findAll { k, v -> k in gridConfig.externalParams }}]")
        params.findAll { k, v -> k in ['id'] }
    }

@tudor-malene
Copy link
Owner

You can also change the gsp template:

    url: '${g.createLink(controller: attrs.controller, action: "${gridConfig.id}Rows", params: params.findAll{it.key in ['id']})}',

@ericraskin
Copy link

Has there been any update on this yet? I am back from vacation and getting back to work. :-/ Have you managed to get externalParams fixed?

@tudor-malene
Copy link
Owner

Hi Eric,
Not yet.
I'll try to make some time for it until next week.

@tudor-malene
Copy link
Owner

fixed in 1.6.4.

You can do:

def yourGrid={
....
    externalParams ( ['id'])
...
}

and the 'id' parameter will be accessible

@ericraskin
Copy link

I am now running version 1.6.5.

In my case, I have a column named "ordnum" { type 'id', property 'ordnum' }. That is the key I need to pass into my subGrid. I have added externalParams(['ordnum']) in the main grid to make it visible to the subGrid. In the subGrid, I have:

        dataSourceType 'gorm'
        domainClass Ordline
        globalFilterClosure { params ->
            rentalOrder {
                eq ('ordnum', params.ordnum ? params.ordnum as long: -1l)
            }
        }

It does not work. The subGrid comes up empty each time. I also can't seem to find the right place in the code to set a breakpoint either.

@tudor-malene
Copy link
Owner

I think it would be easier if you could send me a running grails project - basically a stripped down version of this setup. ( ideally with some data added in BootStrap), so we have a better reference.

@ericraskin
Copy link

Sorry for the long delay on this. Unfortunately, my wife took ill and passed away. I haven't been able to get back to this until now. :-/

I know you asked for a project to play with. I will try to create one.

In any event, with fresh eyes, I noticed that your _jqGridRenderer.gsp template contains:

    url: '${g.createLink(controller: attrs.controller, action: "${gridConfig.id}Rows", 
             params: GridUtils.externalParams(gridConfig))}',
    loadError: easygrid.loadError,
    pager: '#${pagerId}',
    ${JsUtils.convertToJs(conf - [navGrid: conf.navGrid] - [filterToolbar: conf.filterToolbar], gridId, true)},
    <g:if test="${gridConfig.subGrid}">
        subGrid: true,
        subGridRowExpanded: easygrid.subGridRowExpanded('${g.createLink(controller: attrs.controller, 
                    action: "${gridConfig.subGrid}Html")}'),
    </g:if>

What looks strange to me is that the url createLink has a params map but the subGrid createLink does not. Worse yet, the params for each row of the subGrid have to be different - based on the data. I need some help understanding how all of this works.

I see that you have the easygrid.subGridRowExpanded call, which seems to take the baseURL that links to the subGrid and then passes information that identifies the particular row in the data attribute. I'm not quite clear on how that gets used by grails to load the subGrid rows and/or jqgrid to display them. Also, I can't find any provisions for other parameters to be supplied to the subgrid. In my case, I have a globalFilterClosure like this in my subgrid:

globalFilterClosure { params ->
    rentalOrder {
        eq ('ordnum', params.ordnum ? params.ordnum as long: -1l)
    }
}

Somehow I have to get that "ordnum" into the params inside the subGrid. It is different for each subGrid I expand, so it can't really be in the params for the enclosing grid.

How do I get that ordnum passed in and referenced properly in the globalFilterClosure?

@ericraskin
Copy link

I FINALLY figured it out!. I had a whole bunch of confusion:

  1. The externalParams setting is used IN THE SUBGRID. It tells the subgrid what value(s) in the parameters should be extracted from the enclosing grid's params map.
  2. My ordnum field was created as type 'id'. This means that its name in the params map is NOT 'ordnum' but rather 'id'.

So, as an example, my enclosing grid contains:

    def managerListOrdersGrid = {
        dataSourceType 'gorm'
        domainClass PASOrder
        idColName 'ordnum'
        subGrid 'managerListOrderDetails'
                          ,
                          , 
                          .
        columns {
            ordnum {
                type 'id'
                property 'ordnum'
                label "PAS Num"
                jqgrid {
                    width "75"
                    align "center"
                }
            }
                              .
                              .
                              .

and my subgrid contains:

    def managerListOrderDetailsGrid = {
        dataSourceType 'gorm'
        domainClass Ordline
        externalParams ( ['id'] )
        globalFilterClosure { params ->
            rentalOrder {
                eq ('ordnum', params.id ? params.id as long: -1l)
            }
        }
                            .
                            .
                            .

This now works as desired. I hope somebody else finds this helpful.

@tudor-malene
Copy link
Owner

Hi Eric,
I'm so sorry to hear that.
I am really saddened to hear of your loss. I don't know what to say... My deepest condolences to you and your family.

Returning to easygrid...
Your settings are correct.
Basically when you open a subgrid in the master grid , the 'Html' method of the subGrid is called with an externalParam named 'id'. This method then renders the _jqGridTemplate and sends it to the browser via ajax.
So, indeed , this is actually a bug in easygrid because 'id' should be a default externalParam for any subgrid. Maybe a more descriptive name for it would be 'masterId'

Thanks for digging into this.

@ericraskin
Copy link

Thanks very much. There is not much to say, but I appreciate the sentiment.

This issue is now fixed for me. Thanks for your help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants