Closed ericraskin closed 10 years ago
I've been digging through this code. I see a call to "easygrid.subGridRowExpanded" in your template, but I can't find that code anywhere. I'm stumped. :-)
You can find that javascript function in easygrid\web-apps\js\jqgridutils\utils.js . This resource is declared in the easygrid resources module ,so it will be loaded all the time.
Here is how subgrids works:
Thanks. I will look for it. But I'm still not clear how the subgrid gets parameters passed in. How does I reference the values from the master row so I can load the proper rows for the subgrid?
On 04/10/2014 05:26 AM, Tudor Malene wrote:
You can find that javascript function in easygrid\web-apps\js\jqgridutils\utils.js . This resource is declared in the easygrid resources module ,so it will be loaded all the time.
Here is how subgrids works:
- Basically all you need to do is declare the subgrid property on the main grid.
- when you do this, the template will render that subgridRowExpanded function that will call the 'Html' action for that subgrid ( That action will actually return the javascript & html code for the subgrid, which in turn, when loaded, will call the Rows method ) . The drawback on this approach , (for now), is that you will have to set all the view properties for the subgrid in the controller.
— Reply to this email directly or view it on GitHub https://github.com/tudor-malene/Easygrid/issues/65#issuecomment-40058732.
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
In that javascript function the "row id" is passed and appended to the 'Html' url. Which in turn uses it to retreive the rows. So, basically, in the globalFilterClosure, the parent row id = params.id
I see. Unfortunately, my field is not named "id" in the master or detail rows. I wonder if that has anything to do with it. My id is "ordnum" in the master row and "ord_ordnum" (part of a composite key) in the detail row.
I will try to read the code, but I haven't found it yet. :-/ I'm using ggts on Linux and sometimes it behaves strangely.
On 04/10/2014 09:05 AM, Tudor Malene wrote:
In that javascript function the "row id" is passed and appended to the 'Html' url. Which in turn uses it to retreive the rows. So, basically, in the globalFilterClosure, the parent row id = params.id
— Reply to this email directly or view it on GitHub https://github.com/tudor-malene/Easygrid/issues/65#issuecomment-40075043.
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
Each row must have an id, provided by the column with the name: 'idColName'. it's returned in the json response from the server
Yep. Thanks. I am tracking all of this through my Firebug. The funny thing is I can't find the easygrid javascript on the running pages. i can find the jqgrid definition and my javascript in the DOM, but I can't find your javascript anywhere.
I assume it is there somewhere because I'm not getting any errors in the console.
I had put a breakpoint on the grails side in the globalFilterClosure for the subgrid and it did not stop. I watched network transfers from the Firebug side when I clicked to open the subgrid and nothing transferred. I'm 99% sure that Firebug shows ajax transfers, but maybe I'm wrong.
The whole thing has me very confused, but I'll figure it out eventually.
On 04/10/2014 11:11 AM, Tudor Malene wrote:
Each row must have an id, provided by the column with the name: 'idColName'. it's returned in the json response from the server
— Reply to this email directly or view it on GitHub https://github.com/tudor-malene/Easygrid/issues/65#issuecomment-40097356.
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
That javascript file is bundled together with jqgrid ( the resources plugin does this ).
Regarding the subgrid, does it open when you expand a row? If not, do you see any javascript error?
It opens, but the display is empty. No headers, no rows.
On 04/10/2014 11:44 AM, Tudor Malene wrote:
That javascript file is bundled together with jqgrid ( the resources plugin does this ).
Regarding the subgrid, does it open when you expand a row? If not, do you see any javascript error?
— Reply to this email directly or view it on GitHub https://github.com/tudor-malene/Easygrid/issues/65#issuecomment-40101489.
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
any errors?
Not that I can find. That's what is so strange. It just opens up an empty row on the grid.
On 04/10/2014 11:47 AM, Tudor Malene wrote:
any errors?
— Reply to this email directly or view it on GitHub https://github.com/tudor-malene/Easygrid/issues/65#issuecomment-40101947.
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
what ajax calls do you see? Can you also try this in chrome?
None -- that's part of the problem. I see nothing under the Network tab when I click the subgrid link. That's what makes me think the javascript isn't getting loaded into the page or something. I thought I would see an error about a missing function, but I'm not seeing that either.
It is very strange.
On 04/10/2014 11:52 AM, Tudor Malene wrote:
what ajax calls do you see? Can you also try this in chrome?
— Reply to this email directly or view it on GitHub https://github.com/tudor-malene/Easygrid/issues/65#issuecomment-40102486.
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
Can you send me the source of the page? ( 'view source')
Sure, before or after expanding the subgrid?
On 04/10/2014 11:57 AM, Tudor Malene wrote:
Can you send me the source of the page? ( 'view source')
— Reply to this email directly or view it on GitHub https://github.com/tudor-malene/Easygrid/issues/65#issuecomment-40103539.
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
the source is the same in both cases. The subgrid code is injected dynamically in the DOM
OK.
On 04/10/2014 12:03 PM, Tudor Malene wrote:
the source is the same in both cases. The subgrid code is injected dynamically in the DOM
— Reply to this email directly or view it on GitHub https://github.com/tudor-malene/Easygrid/issues/65#issuecomment-40104212.
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
<!DOCTYPE html>
<html lang="en">
<!--[if lt IE 7 ]> <html lang="en" class="no-js ie6"> <![endif]-->
<!--[if IE 7 ]> <html lang="en" class="no-js ie7"> <![endif]-->
<!--[if IE 8 ]> <html lang="en" class="no-js ie8"> <![endif]-->
<!--[if IE 9 ]> <html lang="en" class="no-js ie9"> <![endif]-->
<!--[if (gt IE 9)|!(IE)]><!--> <html lang="en" class="no-js"><!--<![endif]-->
<head>
<meta charset="utf-8">
<title>Professional Advertising Systems Inc.</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<!-- Latest compiled and minified CSS -->
<link href="//netdna.bootstrapcdn.com/bootswatch/3.1.1/cyborg/bootstrap.min.css" rel="stylesheet" type="text/css" media="screen" >
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
<link href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/themes/start/jquery-ui.min.css" rel="stylesheet">
<link href="/pasweb/static/css/base.black.css" rel="stylesheet" type="text/css">
<!--link href="//netdna.bootstrapcdn.com/bootswatch/3.1.1/cerulean/bootstrap.min.css" rel="stylesheet" type="text/css" media="screen" -->
<!--link href="/pasweb/static/css/base.white.css" rel="stylesheet" type="text/css"-->
<style type="text/css" id="enject"></style>
</head>
<body>
<section id="headerSection">
<div class="navbar navbar-default" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="index">Professional Advertising Systems <small> Inc.</small></a>
</div>
<div class="collapse navbar-collapse" id="navbar-collapse">
<ul class="nav navbar-nav navbar-right">
<li class=""><a href="/pasweb/">Home</a></li>
<li class=""><a href="/pasweb/services">What We Do</a></li>
<li class=""><a href="/pasweb/about_us">About Us</a></li>
<!-- li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="elements">Page Elements</a></li>
<li><a href="comingsoon">Coming soon page</a></li>
</ul>
</li-->
<li class=""><a href="/pasweb/customeraccess">Customer Access</a></li>
<li class=""><a href="/pasweb/contact">Contact Us</a></li>
</ul>
</div>
</div>
</div>
</section>
<!--Header Ends================================================ -->
<section id="bannerSection">
<div class="container">
<div class="col-md-4">
<h1 id="pageTitle">Customer Access</h1>
</div>
<div class="col-md-5"></div>
<div class="col-md-3" style="position:relative; top:30px;">
Logged in as <strong>saavoy</strong> <a href="/pasweb/logout/index" class="btn btn-primary">Logout</a>
</div>
</div>
</section>
<section id="bodySection">
<div class="container-fluid" style="padding-bottom: 10px;">
<div class="col-md-2">
<ul class="nav nav-stacked">
<li><a href="/pasweb/customerAccess/broker_mailers" onclick="jQuery.ajax({type:'POST', url:'/pasweb/customerAccess/broker_mailers',success:function(data,textStatus){jQuery('#mainContent').html(data);},error:function(XMLHttpRequest,textStatus,errorThrown){}});return false;" class="btn btn-primary">Mailers/Merges</a></li>
<li><a href="/pasweb/customerAccess/manager_lists" onclick="jQuery.ajax({type:'POST', url:'/pasweb/customerAccess/manager_lists',success:function(data,textStatus){jQuery('#mainContent').html(data);},error:function(XMLHttpRequest,textStatus,errorThrown){}});return false;" class="btn btn-primary">Lists/Orders</a></li>
</ul>
</div>
<div class="col-md-10">
<div id="mainContent">
</div>
</div>
</div>
</section>
<!-- Footer Start ============================================= -->
<section id="footerSection">
<div class="container">
<footer class="footer well well-sm">
<div class="row text-center">
<div class="col-md-4">
<h4>Visit us</h4>
<address style="margin-bottom:15px;margin-right:-30px">
<strong><a href="index" title="business"><i class="fa fa-home"></i> Professional Advertising Systems Inc. </a></strong><br>
200 Business Park Drive, Suite 304<br>
Armonk, NY 10504<br>
</address>
</div>
<div class="col-md-4">
<h4>Contact Us</h4>
Phone: <i class="icon-phone-sign"></i> 914-765-0500 <br>
Email: <a href="contact" title="contact"><i class="icon-envelope-alt"></i> info@paslists.com</a><br/>
Link: <a href="index" title="Professional Advertising Systems Inc."><i class="fa fa-globe"></i> www.paslists.com</a><br/><br/>
</div>
<div class="col-md-4">
<h4>Quick Links</h4>
<a href="services" title="services"><i class="fa fa-cogs"></i> Services </a><br/>
<a href="about" title=""><i class="fa fa-info"></i> About Us </a><br/>
<a href="contact" title="Contact Us"><i class="fa fa-question"></i> Contact Us </a>
</div>
</div>
<p style="padding:18px 0 44px">© 2014 Professional Advertising Systems Inc., All Rights Reserved </p>
</footer>
</div><!-- /container -->
</section>
<a href="#" class="btn" style="position: fixed; bottom: 38px; right: 10px; display: none; " id="toTop"> <i class="icon-arrow-up"></i> Go to top</a>
<!-- Javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="//platform.twitter.com/widgets.js"></script>
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="//code.jquery.com/jquery-migrate-1.2.1.js"></script>
<!-- Latest compiled and minified JavaScript -->
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script src="/pasweb/static/js/business_ltd_1.0.js"></script>
<script>
/*menu handler*/
$(function(){
function stripTrailingSlash(str) {
if(str.substr(-1) == '/') {
return str.substr(0, str.length - 1);
}
return str;
}
console.log('------------------------');
var url = window.location.pathname;
console.log('url = ' + url);
var activePage = stripTrailingSlash(url);
console.log('activePage = ' + activePage);
if (activePage == '/pasweb') {
activePage = '/pasweb/home';
}
if (activePage == '/pasweb/login/auth') {
activePage = '/pasweb/customeraccess';
}
console.log('activePage = ' + activePage);
$('.nav li a').each(function(){
var currentPage = stripTrailingSlash($(this).attr('href'));
if (currentPage == '/pasweb') {
currentPage = '/pasweb/home';
}
console.log('currentPage = ' + currentPage);
if (activePage == currentPage) {
console.log('setting ' + currentPage + 'active');
$(this).parent().addClass('active');
console.log('set ACTIVE');
}
});
console.log('------------------------');
});
</script>
<script>
$(document).ready(function() {
$('form:first *:input[type!=hidden]:first').focus();
});
</script>
</body>
</html>
I don't see any grid definition
Wait. I gave you bad information. I did see Network traffic when I clicked the link. URL is: https://localhost:8443/pasweb/customerAccess/managerListOrderDetailsHtml?id=30521&gridId=row30521
That does have the ID for one of my orders (30521). So the URL is being built correctly. Here is the reply:
<table id="row30521_table"></table>
<div id="row30521Pager"></div>
<script type="text/javascript">jQuery(function(){
jQuery("#row30521_table").jqGrid({
url:
'/pasweb/customerAccess/managerListOrderDetailsRows/30521?gridId=row30521',
loadError: easygrid.loadError,
pager: '#row30521Pager',
"datatype":"json","viewrecords":true,"width":"100%","height":240,"rowNum":10,"rowList":[10,20,50],"multiSort":true,
colModel: [
{"label":"Keycode","searchoptions":{"clearSearch":false,"sopt":["cn","nc","eq","ne","bw","ew"]},"search":true,"editable":true,"sortable":true,"name":"keycode","width":"100"
},
{"label":"Segment","searchoptions":{"clearSearch":false,"sopt":["cn","nc","eq","ne","bw","ew"]},"search":true,"editable":true,"sortable":true,"name":"segment","width":"150"
},
{"label":"Order
Qty","searchoptions":{"clearSearch":false,"sopt":["eq","ne","lt","le","gt","ge"]},"search":true,"editable":true,"sortable":true,"name":"ordqty","width":"100"
},
{"label":"Ship
Qty","searchoptions":{"clearSearch":false,"sopt":["eq","ne","lt","le","gt","ge"]},"search":true,"editable":true,"sortable":true,"name":"shipqty","width":"100"
},
],
});
jQuery('#row30521_table').jqGrid('navGrid','#row30521Pager',
{"add":false,"view":true,"edit":false,"del":false,"search":true,"refresh":true},
{}, //edit
{}, //add
{}, //delete
{"multipleSearch":true,"multipleGroup":true,"showQuery":true,"caption":"Multi-clause
Searching","closeAfterSearch":true,"sopt":["eq","ne","lt","le","gt","ge","bw","bn","ew","en","cn","nc","nu","nn"]},
//search
{"closeOnEscape":true} //view
)
}); </script>
That is the correct subgrid, so something is coming back. I guess the problem is somewhere in my globalFilterCriteria. Where should I set a breakpoint to debug it? I have one set inside the globalFilterCriteria itself, but the debugger doesn't stop there.
On 04/10/2014 12:03 PM, Tudor Malene wrote:
the source is the same in both cases. The subgrid code is injected dynamically in the DOM
— Reply to this email directly or view it on GitHub https://github.com/tudor-malene/Easygrid/issues/65#issuecomment-40104212.
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
Yep -- it is entirely inside the DOM. It is not in the page source. I use ajax calls to bring up the correct page from my buttons.
Could that be the problem? What draws in the javascript resources when ajax calls are made?
On 04/10/2014 12:10 PM, Tudor Malene wrote:
I don't see any grid definition
— Reply to this email directly or view it on GitHub https://github.com/tudor-malene/Easygrid/issues/65#issuecomment-40105008.
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
The browser doesn't really care how the DOM is populated.
Your code looks good to me, and if you don't see any javascript errors, then it should be ok.
I would try 3 things: 1) Do a manual call to: /pasweb/customerAccess/managerListOrderDetailsRows/30521?gridId=row30521
And please post back what it returns ( also do a call to: /pasweb/customerAccess/managerListOrderDetailsRows) This is a general good way to debug
2) change the browser to chrome, and see if you see any errors in the javascript console there 3) comment out the globalFilterClosure
I think I have found the issue. It is the composite id. I would have to add more code to the domain class to handle it. Even then, I'm not sure how the lookup code will work, as the parameter being passed is only the first part of the composite id. I'm not quite clear how the system will deal with one part of the primary key being null. We want it to load all the records that match, but I think gorm will look for a record with that particular key (second part of id null).
I may just add a surrogate primary key and avoid the whole issue. It should not be too hard to add to my legacy db.
I will post more once I figure this out. On Apr 11, 2014 2:48 AM, "Tudor Malene" notifications@github.com wrote:
The browser doesn't really care how the DOM is populated.
Your code looks good to me, and if you don't see any javascript errors, then it should be ok.
I would try 3 things: 1) Do a manual call to: /pasweb/customerAccess/managerListOrderDetailsRows/30521?gridId=row30521
And please post back what it returns ( also do a call to: /pasweb/customerAccess/managerListOrderDetailsRows) This is a general good way to debug
2) change the browser to chrome, and see if you see any errors in the javascript console there 3) comment out the globalFilterClosure
— Reply to this email directly or view it on GitHubhttps://github.com/tudor-malene/Easygrid/issues/65#issuecomment-40175251 .
First, I modified my setup to get rid of the composite ID. I guess I still did not do it correctly or there is some other problem, because it still did not work.
When I tried to do a manual call, I got this error:
Error 2014-04-11 17:20:36,422 [http-bio-8443-exec-9] ERROR errors.GrailsExceptionResolver - NumberFormatException occurred when processing request: [GET] /pasweb/customerAccess/managerListOrderDetailsRows/30521%3FgridId=row30521 For input string: "30521?gridId=row30521". Stacktrace follows: Message: For input string: "30521?gridId=row30521" Line | Method ->> 65 | forInputString in java.lang.NumberFormatException
| 441 | parseLong in java.lang.Long | 540 | valueOf . . . . . . . . . . . . . . . in '' | 3637 | toLong in org.codehaus.groovy.runtime.StringGroovyMethods
I truncated the stack trace. It seems that more than just the id of the master row (30521) is getting sent as the params.id value. At least, that's what it looks like to me?
Commenting out the globalFilterClosure returns and executing the manual call returns JSON data:
{"rows":[{"id":null,"cell":[null,"Entire File for NCOA",45000,36396]},{"id":null,"cell":[null,"1999 Buyers",5000,4999]},{"id":null,"cell":[null,"0-24 $10+ w/State Select",12500,10767]},{"id":null,"cell":[null,"Active Donors w/SCF Select",6000,5967]},{"id":null,"cell":["N164","0-12 $10+ Donors",30000,29994]},{"id":null,"cell":["HCU136","1999 Buyers",10000,9989]},{"id":null,"cell":["HCU142","1999 Buyers",25000,24994]},{"id":null,"cell":[null,"0-12 $10+ Donors",25000,24989]},{"id":null,"cell":[null,"0-6 $10+ Donors",50000,45383]},{"id":null,"cell":[null,"2nd Qtr 2000 Hotline w/State Omits",5000,4959]},{"id":null,"cell":[null,"0-12 $5+ Donors",100000,100003]},{"id":null,"cell":["7 AO L/J","July 2000 Hotline Buyers",9000,10273]},{"id":null,"cell":["4590","July 2000 HL with State Sels",5000,5002]},{"id":null,"cell":["J14901","July 2000 Julia",1173,1250]},{"id":null,"cell":["ILIS08T1","July 2000 HL w/State Omits",5000,5002]},{"id":null,"cell":["914","Last 12 Mos $10+ Donors",20000,20003]},{"id":null,"cell":[null,"June 2000 Hotline",5000,2986]},{"id":null,"cell":["IDA10G","0-12 $5+ Donors Omit States/SCF",15000,15003]},{"id":null,"cell":[null,"0-24 $5+ Donors",10000,9474]},{"id":null,"cell":[null,"0-24 Mos $5+",10000,9474]}],"page":1,"records":70590,"total":3530}
So, something is clearly wrong with the globalFilterClosure. My latest incarnation is:
globalFilterClosure{ params ->
eq('order', params.id ? params.id as long: -1l)
}
The ordline domain contains (abbreviated):
Long ordline_id
Order order
static mapping = {
table name: 'ordlines', schema:'sbowner'
version false
id column: 'ordline_id', name: 'ordline_id', generator: 'assigned'
order column: 'ord_ordnum'
}
What should I try now?
On 04/11/2014 02:48 AM, Tudor Malene wrote:
The browser doesn't really care how the DOM is populated.
Your code looks good to me, and if you don't see any javascript errors, then it should be ok.
I would try 3 things: 1) Do a manual call to: /pasweb/customerAccess/managerListOrderDetailsRows/30521?gridId=row30521
And please post back what it returns ( also do a call to: /pasweb/customerAccess/managerListOrderDetailsRows) This is a general good way to debug
2) change the browser to chrome, and see if you see any errors in the javascript console there 3) comment out the globalFilterClosure
— Reply to this email directly or view it on GitHub https://github.com/tudor-malene/Easygrid/issues/65#issuecomment-40175251.
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
Try this:
globalFilterClosure{ params ->
eq('order', params.long('id', -1l))
}
Unfortunately, no change. :-(
On 04/14/2014 02:52 AM, Tudor Malene wrote:
Try this:
globalFilterClosure{ params -> eq('order', params.long('id', -1l)) } — Reply to this email directly or view it on GitHub https://github.com/tudor-malene/Easygrid/issues/65#issuecomment-40337504.
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
You mean, you get the exception?
No -- no exception. When I use your new example globalFilterClosure and I go to URL: https://localhost:8443/pasweb/customerAccess/managerListOrderDetailsHtml?id=30521&gridId=row30521
I get nothing returned. I still don't have the access from Orders to Ordlines correct.
Where can I set a breakpoint in your code to watch the ajax json response being built on the server for the subgrid? Maybe if I can stop there I can see what is wrong with the globalFilterClosure.
So, this is definitely not an Easygrid issue right now. I opened the console and did this:
import pasweb.Order
import pasweb.Ordline
def order = Order.withCriteria{
eq('ordnum',30810l)
}
println order
def ordlines = Ordline.withCriteria{
eq('order',30810l)
}
The println works fine, but I get the following error on the Ordlines lookup:
2014-04-15 14:19:50,137 [Thread-19] ERROR property.BasicPropertyAccessor - IllegalArgumentException in class: pasweb.Order, getter method of property: ordnum
Exception thrown
So, clearly something is not happy with the "long" type somewhere. I will have to research this at the hibernate level, I think. Open to suggestions if you have them.
Looks to me like you should do this:
def ordlines = Ordline.withCriteria{
order{
eq('ordnum',30810l)
}
}
Actually, that is the first thing I tried. I get this:
Order = [30810]
Exception thrown
groovy.lang.MissingMethodException: No signature of method:
java.util.ArrayList.call() is applicable for argument types:
(ConsoleScript20$_run_closure2_closure4) values:
[ConsoleScript20$_run_closure2_closure4@72eea7f5]
Possible solutions: tail(), wait(), last(), last(), max(), any()
at ConsoleScript20$_run_closure2.doCall(ConsoleScript20:11)
at ConsoleScript20$_run_closure2.doCall(ConsoleScript20)
at
org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1260)
at
grails.orm.HibernateCriteriaBuilder.invokeClosureNode(HibernateCriteriaBuilder.java:1854)
at
grails.orm.HibernateCriteriaBuilder.invokeMethod(HibernateCriteriaBuilder.java:1553)
at
org.grails.datastore.gorm.GormStaticApi$_withCriteria_closure11.doCall(GormStaticApi.groovy:305)
at
org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1260)
at com.sun.proxy.$Proxy39.doInSession(Unknown Source)
at
org.grails.datastore.mapping.core.DatastoreUtils.execute(DatastoreUtils.java:302)
at
org.grails.datastore.gorm.AbstractDatastoreApi.execute(AbstractDatastoreApi.groovy:37)
at
org.grails.datastore.gorm.GormStaticApi.withCriteria(GormStaticApi.groovy:304)
at pasweb.Ordline.withCriteria(Ordline.groovy)
at pasweb.Ordline$withCriteria.call(Unknown Source)
at ConsoleScript20.run(ConsoleScript20:10)
On 04/16/2014 02:48 AM, Tudor Malene wrote:
Looks to me like you should do this:
def ordlines = Ordline.withCriteria{ order{ eq('ordnum',30810l) } } — Reply to this email directly or view it on GitHub https://github.com/tudor-malene/Easygrid/issues/65#issuecomment-40568247.
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
This looks to me like a bug in grails. You should create a small test project and file a bug in http://jira.grails.org/
I am working on creating the test case. I'm beginning to think that everything I "knew" about GORM is wrong. :-( I can't even get a simple association to work properly. I broke the test case into:
class TestOrder {
Long ordnum
String ord_type
static hasMany = [ orderDetail: TestOrdline ]
static mapping = {
id column: 'ordnum', name: 'ordnum', generator: 'assigned'
}
static constraints = {
}
}
class TestOrdline {
Long ordline_id
Long linenum
static belongsTo = [order:TestOrder]
static mapping = {
id column: 'ordline_id', name: 'ordline_id', generator: 'assigned'
}
static constraints = {
}
}
Here's my test (using JUnit):
class Show_errorTest extends GroovyTestCase {
def testOrder1
def testOrder2
def setup() {
testOrder1 = new TestOrder(ordnum: 12345l, ord_type: 'LRO')
testOrder1.save(flush:true)
def testOrdline11 = new TestOrdline(order: testOrder1,
linenum: 1, ordline_id: 100)
testOrdline11.save(flush:true)
def testOrdline12 = new TestOrdline(order: testOrder1,
linenum: 2, ordline_id: 101)
testOrdline12.save(flush:true)
testOrder2 = new TestOrder(ordnum: 54321l, ord_type: 'LRO')
testOrder2.save(flush:true)
def testOrdline21 = new TestOrdline(order: testOrder2,
linenum: 1, ordline_id: 102)
testOrdline21.save(flush:true)
}
def cleanup() {
testOrder1.delete
testOrder2.delete
}
void testError() {
setup()
def orderList = TestOrder.withCriteria{
eq('ordnum',12345l)
}
def order = orderList[0]
println "order loaded"
assert order
assertEquals 12345, order.ordnum
println "order: Order=${order.ordnum}"
assertEquals 2, order.orderDetail.size()
println "orderDetail: Count=${order.orderDetail.size()}"
order.orderDetail.each {
println "orderDetail: Order=${it.order.ordnum}
Line=${it.linenum} id=${it.ordline_id}"
}
cleanup()
}
}
When I run this, the "assertEquals 2, order.orderDetail.size()" fails. When I run this in the debugger, I see that the orderDetail entry for the order object is null! It's an association! Why doesn't it have a proxy object? I'm accessing it! Why doesn't the proxy change to actual detail objects?
I am completely confused now.
Eric
in your setup method , you should do:
testOrder1.addToOrderDetails(testOrdline11 )
for each order line.
Yep -- that fixed the problem. I'm not quite sure why that was necessary, since I did link them together by providing the Order object when I created the OrderDetail object. I will just have to remember that this is necessary.
The funny thing is I posted this on the grails-user list and somebody came back with a (supposedly) working Spock test, using my setup() routine as written. They did not need the addToOrderDetail() call. :-/ I guess they didn't actually run the code they wrote.
I have now successfully created a test that shows the issue. It is posted as JIRA GRAILS-11336.
So, I found out what the bug in my test case is. I had used the same name for a local variable and a class. Groovy was taking the local variable instead of the class in the DSL.
def order=...
def testordline = Ordline.withCriteria {
order {
....
}
}
The "order" in my def was being used, instead of my association named "order" in Ordline.
I have renamed all of my fields in all of my domain classes so that no field name is the same as a class name. There should be no possible name collisions now.
Unfortunately, I still can't get the subgrid to show any data. However, now my test shows that the globalFilterCriteria should work. At least, it pulls up valid data in my tests. It does NOT work, however, when I use the ajax URL in the Firefox. Per your request in an earlier message, I have also tried it in Chrome. This URL:
/pasweb/customerAccess/managerListOrderDetailsHtml?id=38788&gridId=row38788
shows in the javascript console, but no data comes back.
Note that I upgraded to 1.5.1 this morning.
I still haven't found the place in the code where the ajax call for the subgrid is processed. I put a breakpoint inside GormDatasourceService.list(). The breakpoint gets hit on master and child grids, but not on subgrids. Where should I put a breakpoint -- or where is the plumbing that links the URL with the code so I can see how it fits together? There is a URL in the subgrid for the ajax call. How is that URL mapped to server code?
This was one tricky bug. Good thing you sorted it out.
This is what learning grails the hard way means :)
To solve this subgrid problem faster, do you think it's possible that you create a very small test project just with those 2 domains and grids and submit it here, so I can debug it?
I tried to isolate it for you, but the test project worked. It just doesn't work in my real project.
Weirder yet, if I change the exact same grid from a subgrid to a child grid in my real project, it works fine. :-( It just fails as a subgrid. How can that be?
This thread has grown pretty large. I'm a little confused : So, you have those 2 grids:
What happens when you open a row in the master grid? Exception? javascript error in the console? nothing? a table shows up but doesn't load the rows? What network calls are made by the browser?
If you remove the 'subGrid' property from the master grid, and use the 2 grids as master-detail grids ( wired via the taglibs), you said it worked properly?
If you like, we can close this and start a new thread.
Yes, that is correct. There are no javascript errors that I can find. No errors on the server side either. It just doesn't return any data.
When I remove the subGrid and add a masterGrid and childParamName in the view, it works fine with no other changes. Note, I'm showing you all three grids here. The grid with a subGrid is itself a child grid.
<div class="row">
<div class="col-md-10">
<p>Click on a List to view the rental orders</p>
<grid:grid name="managerList">
<grid:set width="auto" height="auto" caption="Lists" />
<grid:set col="counts" label="Counts" align="center" formatter="f:countsViewButton" />
</grid:grid>
</div>
</div>
<br/>
<div class="row">
<div class="col-md-10">
<p>Click on an order to view the order details</p>
<grid:grid name="managerListOrders" masterGrid="managerList" childParamName="listId">
<grid:set width="auto" height="auto" caption="Rental Orders"/>
</grid:grid>
<grid:exportButton name="managerListOrders" formats="['excel','csv','pdf']"/>
</div>
</div>
<!--div class="row">
<div class="col-md-10">
<grid:grid name="managerListOrderDetails" masterGrid="managerListOrders" childParamName="id" jqgrid.caption='"Rental Orders"'/>
<grid:exportButton name="managerListOrderDetails" formats="['excel','csv','pdf']"/>
</div>
</div-->
When I go back to a grid with a subGrid, the subGrid does not display anything. It opens up on the jqgrid display, but it just shows a single blank line. There isn't even an "empty" subgrid displayed.
Could the fact that the grid with the subGrid is a child grid make a difference somehow? I will have to add that to my test.
So, the same grid, is on the same page both a subgrid and a child grid?
Nope - one or the other. Mutually exclusive. I tried it as a subgrid and it didn't work. I then changed the definition (commented out the subgrid) and changed the view to display as a child grid. It worked.
The main difference between the 2 is that, for the subgrid , the grid is added to the DOM from the html code generated by that Html call. But it's odd that you see no javascript error. Does the browser even make that call?
It appears to. When I look at network traffic, a call goes out. Nothing comes back
could you run that call and check out the response? What is the exact call ?
https://localhost:8443/pasweb/customerAccess/managerListOrderDetailsHtml?id=38788&gridId=row38788 is the URL.
Response is:
<table id="row38788_table"></table>
<div id="row38788Pager"></div>
<script type="text/javascript">jQuery(function(){
jQuery("#row38788_table").jqGrid({
url: '/pasweb/customerAccess/managerListOrderDetailsRows/38788?gridId=row38788',
loadError: easygrid.loadError,
pager: '#row38788Pager',
"datatype":"json","viewrecords":true,"width":"100%","height":240,"rowNum":10,"rowList":[10,20,50],"multiSort":true,
colModel: [
{"label":"Keycode","searchoptions":{"clearSearch":false},"search":false,"sortable":true,"name":"keycode","width":"100"
},
{"label":"Segment","searchoptions":{"clearSearch":false},"search":false,"sortable":true,"name":"segment","width":"150"
},
{"label":"Order Qty","searchoptions":{"clearSearch":false},"search":false,"sortable":true,"name":"ordqty","width":"100"
},
{"label":"Ship Qty","searchoptions":{"clearSearch":false},"search":false,"sortable":true,"name":"shipqty","width":"100"
},
],
});
jQuery('#row38788_table').jqGrid('navGrid','#row38788Pager',
{"add":false,"view":true,"edit":false,"del":false,"search":true,"refresh":true},
{}, //edit
{}, //add
{}, //delete
{"multipleSearch":true,"multipleGroup":true,"showQuery":true,"caption":"Multi-clause Searching","closeAfterSearch":true,"sopt":["eq","ne","lt","le","gt","ge","bw","bn","ew","en","cn","nc","nu","nn"]}, //search
{"closeOnEscape":true} //view
)
}); </script>
Console shows:
POST https://localhost:8443/pasweb/j_spring_security_check [HTTP/1.1 302 Found 121ms]
GET https://localhost:8443/pasweb/customeraccess [HTTP/1.1 200 OK 309ms]
"JQMIGRATE: Logging is active" jquery-migrate-1.2.1.js:21
"------------------------" customeraccess:154
"url = /pasweb/customeraccess" customeraccess:156
"activePage = /pasweb/customeraccess" customeraccess:159
"activePage = /pasweb/customeraccess" customeraccess:167
"currentPage = /pasweb/home" customeraccess:174
"currentPage = /pasweb/services" customeraccess:174
"currentPage = /pasweb/about_us" customeraccess:174
"currentPage = /pasweb/customeraccess" customeraccess:174
"setting /pasweb/customeraccessactive" customeraccess:177
"set ACTIVE" customeraccess:179
"currentPage = /pasweb/contact" customeraccess:174
"currentPage = /pasweb/customerAccess/broker_mailers" customeraccess:174
"currentPage = /pasweb/customerAccess/manager_lists" customeraccess:174
"------------------------" customeraccess:182
POST https://localhost:8443/pasweb/customerAccess/manager_lists [HTTP/1.1 200 OK 961ms]
GET https://localhost:8443/pasweb/static/plugins/jquery-1.11.0/js/jquery/jquery-1.11.0.min.js [HTTP/1.1 200 OK 10ms]
GET https://localhost:8443/pasweb/static/bundle-bundle_easygrid-jqgrid-dev_head.js [HTTP/1.1 200 OK 7ms]
GET https://localhost:8443/pasweb/static/plugins/jquery-ui-1.8.24/jquery-ui/js/jquery-ui-1.8.24.custom.js [HTTP/1.1 200 OK 5ms]
TypeError: jQuery(...).jqGridMethod is not a function jquery-1.11.0.min.js:3
GET https://localhost:8443/pasweb/customerAccess/managerListRows [HTTP/1.1 200 OK 2374ms]
GET https://localhost:8443/pasweb/customerAccess/managerListOrdersRows [HTTP/1.1 200 OK 150ms]
GET https://localhost:8443/pasweb/customerAccess/managerListOrdersRows [HTTP/1.1 200 OK 360ms]
GET https://localhost:8443/pasweb/customerAccess/managerListOrderDetailsHtml [HTTP/1.1 200 OK 36ms]
"/pasweb/customerAccess/managerListOrderDetailsHtml?id=38788&gridId=row38788" jquery-1.11.0.min.js:13442
GET https://localhost:8443/pasweb/customerAccess/managerListOrderDetailsHtml [HTTP/1.1 200 OK 37ms]
Note that some of this is my own debugging info for other parts of the site.
Screen shot showing results:
As you can see, the subgrid opens up empty.
Seems like we'll have to do some javascript debugging.
Go to: \js\jqgridutils\utils.js - in the easygrid plugin, and find the property: subGridRowExpanded There you will find a function:
subGridRowExpanded: function (baseUrl) {
return function (subgrid_id, row_id) {
var url = baseUrl + "?id=" + row_id + "&gridId=row" + row_id;
console.log(url);
$.ajax({
url: url,
dataType: "html",
success: function (data) {
jQuery("#" + subgrid_id).html(data);
}
});
}
},
This function is actually called when you expand the row. The problem seems to be with the success callback. You should add some console.log messages there to see what's going on:
success: function (data) {
console.log('subgrid loaded');
console.log(data);
jQuery("#" + subgrid_id).html(data);
console.log('after loading');
}
Let me know how that goes.
So, here is the output:
GET https://localhost:8443/pasweb/customerAccess/managerListOrderDetailsHtml [HTTP/1.1 200 OK 43ms]
"/pasweb/customerAccess/managerListOrderDetailsHtml?id=38788&gridId=row38788" jquery-1.11.0.min.js:13442
"subgrid loaded" jquery-1.11.0.min.js:13447
"
<table id="row38788_table"></table>
<div id="row38788Pager"></div>
<script type="text/javascript">jQuery(function(){
jQuery("#row38788_table").jqGrid({
url: '/pasweb/customerAccess/managerListOrderDetailsRows/38788?gridId=row38788',
loadError: easygrid.loadError,
pager: '#row38788Pager',
"datatype":"json","viewrecords":true,"width":"100%","height":240,"rowNum":10,"rowList":[10,20,50],"multiSort":true,
colModel: [
{"label":"Keycode","searchoptions":{"clearSearch":false},"search":false,"sortable":true,"name":"keycode","width":"100"
},
{"label":"Segment","searchoptions":{"clearSearch":false},"search":false,"sortable":true,"name":"segment","width":"150"
},
{"label":"Order Qty","searchoptions":{"clearSearch":false},"search":false,"sortable":true,"name":"ordqty","width":"100"
},
{"label":"Ship Qty","searchoptions":{"clearSearch":false},"search":false,"sortable":true,"name":"shipqty","width":"100"
},
],
});
jQuery('#row38788_table').jqGrid('navGrid','#row38788Pager',
{"add":false,"view":true,"edit":false,"del":false,"search":true,"refresh":true},
{}, //edit
{}, //add
{}, //delete
{"multipleSearch":true,"multipleGroup":true,"showQuery":true,"caption":"Multi-clause Searching","closeAfterSearch":true,"sopt":["eq","ne","lt","le","gt","ge","bw","bn","ew","en","cn","nc","nu","nn"]}, //search
{"closeOnEscape":true} //view
)
}); </script>
" jquery-1.11.0.min.js:13448
"after loading"
Looks just like what I posted before, so that is what is really coming back from the server.
I put more of my regular site into the test and it still worked. I have ruled out the child grid status as being the issue.
As usual, here comes a long post. Trying to anticipate what you might need to answer the question. ;-)
I can't quite figure out how a subgrid links to a grid. I know you say it is like a master-detail grid in the docs, but I'm not getting it yet. In the master-detail grid, you put a masterGrid and a childParamName in the GSP, and then you put a GlobalFilter in to compare the parameter with the data. There is no place to put that for a subgrid in the GSP, so how do I pass a parameter for the subgrid? Here's my code:
GSP (yes, this particular grid is a detail grid for another one defined previously. This detail grid contains the subgrid)
Controller:
My data comes from legacy tables in an Oracle database. The id column for the Orders table is "ordnum", declared like this:
Ordline (the subgrid data) looks like this:
I need to link the ordnum column in the Orders table with the ord_ordnum column in the Ordlines table. I wasn't sure how to do this, so I created a hidden column named "id" in the main grid and put the ordnum in as its value. I also set idColName 'ordnum', hoping that would link them up.
This hasn't worked. When I expand any subgrid row, it is empty. I can't quite figure out how to link everything up.