{"id":3971,"date":"2011-07-01T14:01:04","date_gmt":"2011-07-01T08:31:04","guid":{"rendered":"http:\/\/www.tothenew.com\/blog\/?p=3971"},"modified":"2016-12-19T15:06:15","modified_gmt":"2016-12-19T09:36:15","slug":"grails-data-binding-criteria-reuse","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/grails-data-binding-criteria-reuse\/","title":{"rendered":"Grails Data Binding &#038; criteria reuse"},"content":{"rendered":"<p>Data Binding in grails is something that I love alot. In most of the cases we look at the Binding with respect to some domain class but binding can be one of the best candidate for searching and filtration.<br \/>\nIn my recent project we had a domain Class Article and the user could filter articles on different criteria. The page looks something like following<\/p>\n<p><a href=\"\/blog\/wp-ttn-blog\/uploads\/2011\/07\/Vis\u00e3o-geral-dos-autores_1309498803105.png\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-3974\" title=\"Vis\u00e3o geral dos autores_1309498803105\" src=\"\/blog\/wp-ttn-blog\/uploads\/2011\/07\/Vis\u00e3o-geral-dos-autores_1309498803105.png\" alt=\"\" width=\"700\" height=\"445\" \/><\/a><\/p>\n<p>We had 3-4 such pages but with some extra states (Enum property) of article. So for doing this we created two CO classes, one for basic search properties like max, offset, order and sort and other for article related fields. So the CO goes like following<\/p>\n<p>[java]<br \/>\nclass SearchCO {<br \/>\n  Integer max = 10<br \/>\n  Integer offset = 0<br \/>\n  String sort = &quot;id&quot;<br \/>\n  String order = &quot;asc&quot;<\/p>\n<p>  def searchCriteria = {<br \/>\n    order(sort, order)<br \/>\n  }<br \/>\n}<\/p>\n<p>class ArticleSearchCO extends SearchCO {<br \/>\n  List&lt;ArticleType&gt; types  \/\/ This is Enum<br \/>\n  List&lt;Long&gt; styleIds<br \/>\n  List&lt;Long&gt; categoryIds<br \/>\n  String topic<br \/>\n  def searchCriteria = {<br \/>\n     and {<br \/>\n      if (topic) {<br \/>\n        ilike(&quot;topic&quot;, &quot;%${topic}%&quot;)<br \/>\n      }<\/p>\n<p>      if (categoryIds) {<br \/>\n        subCategory {<br \/>\n              inList(&quot;id&quot;, categoryIds)<br \/>\n          }<br \/>\n      }<\/p>\n<p>      if (styleIds) {<br \/>\n        writingStyle {<br \/>\n             inList(&quot;id&quot;, styleIds)<br \/>\n         }<br \/>\n      }<\/p>\n<p>      if (types) {<br \/>\n            inList(&quot;type&quot;, types)<br \/>\n        }<br \/>\n    }<br \/>\n    super.searchCriteria<br \/>\n  }<br \/>\n}<br \/>\n[\/java]<\/p>\n<p>In our controller side we got the fully populated object that can be used for searching the different articles based on searching. So our controller side code was something like<\/p>\n<p>[java]<br \/>\ndef findWork = {ArticleSearchCO co -&gt;<br \/>\n    List&lt;Article&gt; articles = authorService.findWork(co)<br \/>\n    render(template:&quot;articles&quot;,model:[articles:articles,totalCount:articles.totalCount])<br \/>\n}<\/p>\n<p>def currentWork = {ArticleSearchCO co -&gt;<br \/>\n    List&lt;Article&gt; articles = authorService.currentWork(co)<br \/>\n    render(template:&quot;articles&quot;,model:[articles:articles,totalCount:articles.totalCount])<br \/>\n}<br \/>\n[\/java]<\/p>\n<p>As I already have the searching closures in my CO so the code in my service was something like<\/p>\n<p>[java]<br \/>\npublic List&lt;Article&gt; findWork(ArticleSearchCO co) {<br \/>\n    def articleCriteria = Article.createCriteria()<br \/>\n    Closure searchCriteria = co.searchCriteria<br \/>\n    searchCriteria.delegate = articleCriteria<br \/>\n    List&lt;Article&gt; articles = articleCriteria.list([max: co.max, offset: co.offset]) {<br \/>\n      eq(&quot;status&quot;, ArticleStatus.Unassigned)<br \/>\n      searchCriteria()<br \/>\n    }<br \/>\n    return articles<br \/>\n  }<br \/>\n[\/java]<\/p>\n<p>In the same way for currentWork method I just changed the status i.e; ArticleStatus.InProgress. Thats how I handled the searching, filtering, pagination which was all Ajax. I tried to make my code as DRY as possible . There are still few things that I dont like about it one is so many if statements and other is delegating the searching criteria in each method. I think now with the support of namedQuery I can optimize the method.<br \/>\n<\/p>\n<p>Hope it helps<br \/>\n<a href=\"http:\/\/www.tothenew.com\/blog\/author\/uday\/\">Uday Pratap Singh<\/a><br \/>\n<a href=\"mailto:uday@intelligrape.com\">uday@intelligrape.com<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Data Binding in grails is something that I love alot. In most of the cases we look at the Binding with respect to some domain class but binding can be one of the best candidate for searching and filtration. In my recent project we had a domain Class Article and the user could filter articles [&hellip;]<\/p>\n","protected":false},"author":11,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":24},"categories":[7],"tags":[602,606,607,601,604,605],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/3971"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/11"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=3971"}],"version-history":[{"count":0,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/3971\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=3971"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=3971"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=3971"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}