SlideShare a Scribd company logo
GRAILS & DOJO
About Sven Using Groovy & Grails since Aug 2006 Grails Podcast, Groovy Series Working at Yahoo!, Inc Find out yourself www.svenhaiges.de
Goals You know how to get started! You know how AJAX is supported by Grails Tags, Libraries, Abstraction Layer You know why Groovy & Grails support your AJAX development, using Dojo Controllers & Actions, render(), Builders, Templates Tipps, gotchas, further resources
Getting Started
Getting started… Install Grails – done! Install Dojo Best download from dojotoolkit.org Place in web-app/js Or use the CDN version of dojo, no installation on your own server! ‘grails install-dojo’ installs dojo 0.4.3 !
How to add Dojo to your pages 0.4.3: Load the dojo core library in your pages <g:javascript library=&quot;dojo&quot; />  Want to use dojo 0.9? Just use CDN: <script type=&quot;text/javascript&quot; djConfig=&quot;isDebug: true&quot; src=&quot;http://o.aolcdn.com/dojo/0.9.0/dojo/dojo.xd.js&quot;></script> <script type=&quot;text/javascript&quot;> dojo.addOnLoad(function(){ alert('loaded, all good'); }); </script>
Understanding Grails & AJAX What a surprise, Grails can serve JavaScript, too! Grails supports AJAX with special tags that provide basic AJAX support for these libraries: prototype, Yahoo! UI, Dojo Abstraction Layer Dojo currently has to be installed separately, Y UI and Prototype come with.
Dojo is more than AJAX Many say AJAX but really mean AJAX + Widgets.  Dojo is very strong in Widgets. Besides this, you get way more: package system, animations, utilities, ShrinkSafe… But: you have to code this in your own code, in javascript. No tags can help you here.
Learning Path Get familiar with Grails Use some Grails AJAX Tags in your pages, see what source code they generate Experiment with your own Javascript / Dojo code Really understand JavaScript & CSS
Grails AJAX Tags
 
remoteLink Creates an <a> Link, submits the request via AJAX and is capable of replacing a div upon response. Several onXXX Methods to customize the call. <div id=&quot;message&quot;></div> <g:remoteLink  action=&quot;remoteLinkCallId&quot;  id=&quot;1&quot;  update=&quot;message&quot;> AJAX Call, id=1 </g:remoteLink> def remoteLinkCallId = {  log.debug(&quot;${actionName} Action called with ${params.id}&quot;) render &quot;You called ${actionName} in ${controllerName} with   ${params.id}&quot; }
formRemote Creates a <form> that will submit all input fields via AJAX.  <g:formRemote  url=&quot;[action:'formRemoteCall']&quot;  name=&quot;form2&quot;  update=&quot;message&quot;  onLoading=&quot;toggleSpinner(true)&quot;  onLoaded=&quot;toggleSpinner(false)&quot; > User: <input name=&quot;user&quot; type=&quot;text&quot;></input> <input type=&quot;submit&quot; value=&quot;formRemote Call&quot;></input> </g:formRemote>  def formRemoteCall = {  log.debug(&quot;${actionName} Action called with ${params.user}&quot;) render &quot;You called ${actionName} in ${controllerName} with     ${params.user}&quot; }
submitToRemote Same as formRemote, just the submit logic is executed on a specific submit button, not all submit buttons. <g:javascript library=&quot;dojo&quot; /> <g:javascript> dojo.require(&quot;dojo.io.IframeIO&quot;); </g:javascript> <g:form  url=&quot;[action:'submitToRemoteCall']&quot; id=&quot;form2&quot;  enctype=&quot;multipart/form-data&quot;> File: <input name=&quot;someFile&quot; type=&quot;file&quot;></input> <g:submitToRemote  value=&quot;Submit Upload&quot;  name=&quot;form2&quot;  action=&quot;submitToRemoteUpload&quot;  update=&quot;[success:'message',failure:'error']&quot; /> </g:form>
submitToRemote Form uploads require us to send the response in an HTML textarea field!  def submitToRemoteUpload =  { def f = request.getFile('someFile')   if(f.empty) { render &quot;No file!&quot; } else { def fileName = f.getOriginalFilename() render(text:&quot;<html><body><textarea>You called ${actionName} in ${controllerName} with file ${fileName}</textarea></body></html>&quot;, contentType:&quot;text/html&quot;, encoding:&quot;UTF-8&quot;) }   }
remoteField Creates an <input> field that submits itself automatically <g:remoteField before=&quot;if (this.value.length < 3) return false;&quot;  action=&quot;quickSearch&quot; update=&quot;tableContent&quot; name=&quot;search&quot;  paramName=&quot;search&quot;/> <span id=&quot;spinner&quot; style=&quot;display:none;&quot;> <img src=&quot;${createLinkTo(dir:'images',file:'spinner_mac.gif')}&quot; alt=&quot;Spinner&quot; /> </span> def  quickSearch = { def  devices = Device.findAllByModelLike(&quot;%${params.search}%&quot;,  [max:20,  sort :&quot;model&quot;, order:'asc']) render(template:'tableContent', model:[deviceList:devices]) }
remoteField list.gsp <table> <thead> <tr> ... </tr> </thead> <tbody id=&quot;tableContent&quot;> <g:each in=&quot;${deviceList}&quot; var=&quot;device&quot;>   ... </g:each> </tbody> </table> _tableContent.gsp <g:each in=&quot;${deviceList}&quot; var=&quot;device&quot;> <tr>   <td>${device.id}</td>   ... </tr> </g:each>
onXXX Methods
Grails AJAX Tags Basic AJAX functionality, good to get started or for very easy use cases More complex stuff: master dojo define the content you send yourself 0.9 Complex UI changes
Grails AJAX Tags do not provide Support for Dijit Widgets …  but  Grails is the ideal server part for many data-hungry widgets – next section.
Grails AJAX support
Render() is your best friend Whether you render pure text, html or JSON/XML formatted text, render() does it all. Creating simple responses is quick and easy: render &quot;This is easy.“ render &quot;{font:{id:10, name:'Arial'}}&quot; If you got larger, more complex responses, use a template to keep it clean: render(template:'podcastList', model:[podcasts:Podcast. findAll ()])
Rendering JSON JSON is faster than XML, it should be AJAJ XML is evil, don’t use it Really, guess what’s faster: <?xml version=&quot;1.0&quot; encoding=&quot;ISO-8859-1&quot;?><linked-hash-map> <entry> <string>identifier</string> <string>id</string> </entry> <entry> <string>items</string> <list> <linked-hash-map> <entry> <string>id</string> <long>1</long> </entry> <entry> <string>url</string> <string>http://url1/rss</string> </entry> </linked-hash-map> <linked-hash-map> <entry> <string>id</string> <long>2</long> </entry> <entry> <string>url</string> <string>http://url2/rss</string> </entry> </linked-hash-map> <linked-hash-map> <entry> <string>id</string> <long>3</long> </entry> <entry> <string>url</string> <string>http://url3/rss</string> </entry> </linked-hash-map> <linked-hash-map> <entry> <string>id</string> <long>4</long> </entry> <entry> <string>url</string> <string>http://url4/rss</string> </entry> </linked-hash-map> <linked-hash-map> <entry> <string>id</string> <long>5</long> </entry> <entry> <string>url</string> <string>http://url5/rss</string> </entry> </linked-hash-map> <linked-hash-map> <entry> <string>id</string> <long>6</long> </entry> <entry> <string>url</string> <string>http://url6/rss</string> </entry> </linked-hash-map> <linked-hash-map> <entry> <string>id</string> <long>7</long> </entry> <entry> <string>url</string> <string>http://url7/rss</string> </entry> </linked-hash-map> <linked-hash-map> <entry> <string>id</string> <long>8</long> </entry> <entry> <string>url</string> <string>http://url8/rss</string> </entry> </linked-hash-map> <linked-hash-map> <entry> <string>id</string> <long>9</long> </entry> <entry> <string>url</string> <string>http://url9/rss</string> </entry> </linked-hash-map> <linked-hash-map> <entry> <string>id</string> <long>10</long> </entry> <entry> <string>url</string> <string>http://url10/rss</string> </entry> </linked-hash-map> </list> </entry> </linked-hash-map>  {&quot;identifier&quot;:&quot;id&quot;,&quot;items&quot;:[{&quot;id&quot;:1,&quot;url&quot;:&quot;http://url1/rss&quot;},{&quot;id&quot;:2,&quot;url&quot;:&quot;http://url2/rss&quot;},{&quot;id&quot;:3,&quot;url&quot;:&quot;http://url3/rss&quot;},{&quot;id&quot;:4,&quot;url&quot;:&quot;http://url4/rss&quot;},{&quot;id&quot;:5,&quot;url&quot;:&quot;http://url5/rss&quot;},{&quot;id&quot;:6,&quot;url&quot;:&quot;http://url6/rss&quot;},{&quot;id&quot;:7,&quot;url&quot;:&quot;http://url7/rss&quot;},{&quot;id&quot;:8,&quot;url&quot;:&quot;http://url8/rss&quot;},{&quot;id&quot;:9,&quot;url&quot;:&quot;http://url9/rss&quot;},{&quot;id&quot;:10,&quot;url&quot;:&quot;http://url10/rss&quot;}]} XML or JSON?
JSON is easy to read, too { &quot;identifier&quot;:&quot;id&quot;, &quot;items&quot;: [ { &quot;id&quot;:1, &quot;url&quot;:&quot;http://url1/rss&quot; }, { &quot;id&quot;:2, &quot;url&quot;:&quot;http://url2/rss&quot; }, { &quot;id&quot;:3, &quot;url&quot;:&quot;http://url3/rss&quot; }, { &quot;id&quot;:4, &quot;url&quot;:&quot;http://url4/rss&quot; } ] }
JSON is easy to create, too Then work with it in you app: render(builder:'json')  { element(imagePath: &quot; /app/myimage.png&quot;) } {&quot;element&quot;:{&quot;imagePath&quot;:&quot;/app/myimage.png&quot;}} dojo.io.iframe.send( { url: &quot;/some/url&quot;, form: dojo.byId('formImage'), handleAs: &quot; json &quot;, method: &quot;POST&quot;, handle: function(response, ioArgs)  { var fileName = response.elementImage.fileName; } });
Using converter & Render Converts domain objects to JSON import grails.converters.JSON def podcastJSON = { def podcast = Podcast.get(1) render podcast as JSON }  { &quot;id&quot;:1, &quot;class&quot;:&quot;Podcast&quot;, &quot;author&quot;:&quot;Author1&quot;, &quot;feedURL&quot;:&quot;http://url1/rss&quot; }
Special Dojo Widgets &  Grails
Data-hungry widgets ComboBox Provides a list of acceptable values but user can still enter his own value. Has a value, just like a textbox. FilteringSelect Much like ComboBox, but has label/value like a select. Will set ‘identifier’ as value of selected label. Tree
Dojo ComboBox & Grails GSP <div dojoType=&quot;dojo.data.ItemFileReadStore&quot; jsId=&quot;stateStore&quot; url=&quot;<g:createLink controller=&quot;widget&quot; action=&quot;comboboxConverterData“ />&quot;> </div> <input  dojoType=&quot;dijit.form.ComboBox&quot; store=&quot;stateStore&quot; hasDownArrow=&quot;false&quot; value=&quot;&quot; searchAttr=&quot;url&quot; name=“feed&quot; onChange=&quot;setValue&quot; />
Dojo ComboBox & Grails Grails Action def comboboxConverterData = { def items = [] def podcasts = Podcast.findAll(); podcasts.each { podcast ->  items << [id:podcast.id, url:podcast.feedURL] } def json = [identifier:&quot;id&quot;, items: items] render json as JSON } Using the Grails Converter simplifies the creation of the expected json structure.
Dojo FilterSelect & Grails GSP <div dojoType=&quot;dojo.data.ItemFileReadStore&quot; jsId=&quot;feedStore&quot; url=&quot;<g:createLink controller=&quot;widget&quot; action=&quot;filterSelectData&quot; />&quot;> </div> <input dojoType=&quot;dijit.form.FilteringSelect&quot; id=&quot;chooser&quot; store=&quot;feedStore&quot; searchAttr=&quot;url&quot; name=&quot;feed&quot; autocomplete=&quot;true&quot; pageSize=&quot;5&quot; />
Dojo FilterSelect & Grails Grails Action – the same…but! def filterSelectData = {  def items = [] def podcasts = Podcast.findAll(); podcasts.each { podcast ->  items << [id:podcast.id, url:podcast.feedURL] } def json = [identifier:&quot;id&quot;, items: items] render json as JSON } Once the user has chosen a label from the list, the identifier (here: podcast.id value) will be used as the value of the widget.
Dojo Tree & Grails GSP <div dojoType=&quot;dojo.data.ItemFileReadStore&quot; jsId=&quot;treeStore&quot; url=&quot;<g:createLink controller=&quot;widget&quot; action=&quot;treeData&quot; />&quot;> </div> <div  dojoType=&quot;dijit.Tree&quot;  store=&quot;treeStore&quot;  childrenAttr=&quot;children&quot;  labelAttr=&quot;url&quot;> </div>
Dojo Tree & Grails Grails Action def treeData = {  def items = [] def children = [] (1..3).each { children  << [_reference:&quot;${it}&quot;] } def podcasts = Podcast.findAll(); podcasts.each { podcast ->  items << [id:podcast.id, url:podcast.feedURL,  children:children ] } def json = [ identifier:&quot;id&quot; , label:'url', items: items] render json as JSON }
Tipps & Resources
Resources Download Dojo, check the test directories for tons of examples Dojo API Tool soon available for 0.9 http://www.dojotoolkit.org/api Converters Plugin http://www.grails.org/Converters+Plugin Dynamic Controller Methods, incl. render() grails.org/Controller+Dynamic+Methods
Resources JSON Formatter http://www.curiousconcept.com/jsonformatter Blogs blogs blogs Grails Podcast http://hansamann.podspot.de/rss
THX Y IM/SKYPE hansamann

More Related Content

PPT
Pragmatics of Declarative Ajax
PPT
Developing Gadgets
PPT
Enterprise AIR Development for JavaScript Developers
PPT
Widget Summit 2008
PDF
Web Standards: Fueling Innovation [Web Design World Boston '08]
PPT
What's new in Rails 2?
KEY
Plone Interactivity
Pragmatics of Declarative Ajax
Developing Gadgets
Enterprise AIR Development for JavaScript Developers
Widget Summit 2008
Web Standards: Fueling Innovation [Web Design World Boston '08]
What's new in Rails 2?
Plone Interactivity

What's hot (20)

PPT
WordPress and Ajax
PPT
Even Faster Web Sites at jQuery Conference '09
PDF
Findability Bliss Through Web Standards
PPTX
DevDays09 Internet Explorer 8
PPTX
Fast by Default
PDF
API Technical Writing
PDF
How to make Ajax work for you
PPT
Fast Loading JavaScript
PDF
Challenges of building a search engine like web rendering service
KEY
Intro to html5 Boilerplate
PPTX
สปริงเฟรมเวิร์ค4.1
PPT
Internet Explorer 8 for Developers by Christian Thilmany
PDF
Usability in the GeoWeb
PDF
Don't make me wait! or Building High-Performance Web Applications
PPT
High Performance Ajax Applications
PDF
Web Performance & Search Engines - A look beyond rankings
ODP
10 Things You're Not Doing [IBM Lotus Notes Domino Application Development]
ODP
WebTest - Efficient Functional Web Testing with HtmlUnit and Beyond
PPT
New Browsers
PPTX
LinkedIn Platform at LeWeb 2010
WordPress and Ajax
Even Faster Web Sites at jQuery Conference '09
Findability Bliss Through Web Standards
DevDays09 Internet Explorer 8
Fast by Default
API Technical Writing
How to make Ajax work for you
Fast Loading JavaScript
Challenges of building a search engine like web rendering service
Intro to html5 Boilerplate
สปริงเฟรมเวิร์ค4.1
Internet Explorer 8 for Developers by Christian Thilmany
Usability in the GeoWeb
Don't make me wait! or Building High-Performance Web Applications
High Performance Ajax Applications
Web Performance & Search Engines - A look beyond rankings
10 Things You're Not Doing [IBM Lotus Notes Domino Application Development]
WebTest - Efficient Functional Web Testing with HtmlUnit and Beyond
New Browsers
LinkedIn Platform at LeWeb 2010
Ad

Viewers also liked (20)

PPT
Blues Music.It Does Not Get Any Better Than This
PPT
PDF
Business Intelligence
PDF
Activos Intangibles
PPT
Packing Newsletter October 07
PDF
Planejamento de Marketing
PDF
Plano de Marketing
PPS
S O N E T O[ B O B L A U R A]
PPS
LIBRO DE LAS PREGUNTAS
PDF
Tutorial Blog En Wordpress 2
PDF
Tutorial Blog En Wordpress 3
PDF
Tutorial Blog En Wordpress 1
PPT
CIPA Overview
ODP
Projekt Hardware - Speicher
PPT
Emprendimiento E Innovación Digital
PDF
Tutorial Blog En Wordpress 4
PPS
Nostalgicemails
PPS
11 De Septiembre
PPT
Samenvatting In Beelden
PPT
Apresentação Aquarius
Blues Music.It Does Not Get Any Better Than This
Business Intelligence
Activos Intangibles
Packing Newsletter October 07
Planejamento de Marketing
Plano de Marketing
S O N E T O[ B O B L A U R A]
LIBRO DE LAS PREGUNTAS
Tutorial Blog En Wordpress 2
Tutorial Blog En Wordpress 3
Tutorial Blog En Wordpress 1
CIPA Overview
Projekt Hardware - Speicher
Emprendimiento E Innovación Digital
Tutorial Blog En Wordpress 4
Nostalgicemails
11 De Septiembre
Samenvatting In Beelden
Apresentação Aquarius
Ad

Similar to Grails and Dojo (20)

PPTX
Grails and Ajax
PPT
Grails Introduction - IJTC 2007
PDF
JavaScript Library Overview
PDF
Merb jQuery
PPT
Ajax
PPT
JavaOne 2008 - TS-5764 - Grails in Depth
PDF
Coding Ajax
PDF
JavaScript Libraries (Kings of Code)
PPTX
Grails Advanced
PDF
JavaScript Libraries (@Media)
PDF
Coding Ajax
PPT
my test
PDF
MVC pattern for widgets
PDF
Grails 101
PDF
JavaScript Library Overview
PDF
JavaScript Library Overview (Ajax Exp West 2007)
PDF
Building Real-World Dojo Web Applications
PDF
JavaScript Libraries (Ajax Exp 2006)
PPTX
Introduction to Grails Framework
PDF
IPhone Web Development With Grails from CodeMash 2009
Grails and Ajax
Grails Introduction - IJTC 2007
JavaScript Library Overview
Merb jQuery
Ajax
JavaOne 2008 - TS-5764 - Grails in Depth
Coding Ajax
JavaScript Libraries (Kings of Code)
Grails Advanced
JavaScript Libraries (@Media)
Coding Ajax
my test
MVC pattern for widgets
Grails 101
JavaScript Library Overview
JavaScript Library Overview (Ajax Exp West 2007)
Building Real-World Dojo Web Applications
JavaScript Libraries (Ajax Exp 2006)
Introduction to Grails Framework
IPhone Web Development With Grails from CodeMash 2009

More from Sven Haiges (11)

PDF
NFC and Commerce combined
PDF
End to End Realtime Communication using Mobiel Devices and the Web
PDF
NFC Android Introduction
PDF
Gesture-controlled web-apps
KEY
CouchDB on Android
KEY
NFC on Android - Near Field Communication
PDF
Android UI
KEY
PDF
Grails @ Java User Group Silicon Valley
ODP
Grails 0.3-SNAPSHOT Presentation WJAX 2006 English
ODP
Grails 0.3-SNAPSHOT Presentation WJAX 2006
NFC and Commerce combined
End to End Realtime Communication using Mobiel Devices and the Web
NFC Android Introduction
Gesture-controlled web-apps
CouchDB on Android
NFC on Android - Near Field Communication
Android UI
Grails @ Java User Group Silicon Valley
Grails 0.3-SNAPSHOT Presentation WJAX 2006 English
Grails 0.3-SNAPSHOT Presentation WJAX 2006

Recently uploaded (20)

PDF
Spectral efficient network and resource selection model in 5G networks
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
Empathic Computing: Creating Shared Understanding
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PDF
Modernizing your data center with Dell and AMD
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PPTX
Cloud computing and distributed systems.
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
KodekX | Application Modernization Development
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
PDF
cuic standard and advanced reporting.pdf
PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
Approach and Philosophy of On baking technology
PPT
Teaching material agriculture food technology
Spectral efficient network and resource selection model in 5G networks
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
Reach Out and Touch Someone: Haptics and Empathic Computing
Empathic Computing: Creating Shared Understanding
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
Modernizing your data center with Dell and AMD
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Cloud computing and distributed systems.
Advanced methodologies resolving dimensionality complications for autism neur...
Dropbox Q2 2025 Financial Results & Investor Presentation
KodekX | Application Modernization Development
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Mobile App Security Testing_ A Comprehensive Guide.pdf
Understanding_Digital_Forensics_Presentation.pptx
Chapter 3 Spatial Domain Image Processing.pdf
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
cuic standard and advanced reporting.pdf
Review of recent advances in non-invasive hemoglobin estimation
Approach and Philosophy of On baking technology
Teaching material agriculture food technology

Grails and Dojo

  • 2. About Sven Using Groovy & Grails since Aug 2006 Grails Podcast, Groovy Series Working at Yahoo!, Inc Find out yourself www.svenhaiges.de
  • 3. Goals You know how to get started! You know how AJAX is supported by Grails Tags, Libraries, Abstraction Layer You know why Groovy & Grails support your AJAX development, using Dojo Controllers & Actions, render(), Builders, Templates Tipps, gotchas, further resources
  • 5. Getting started… Install Grails – done! Install Dojo Best download from dojotoolkit.org Place in web-app/js Or use the CDN version of dojo, no installation on your own server! ‘grails install-dojo’ installs dojo 0.4.3 !
  • 6. How to add Dojo to your pages 0.4.3: Load the dojo core library in your pages <g:javascript library=&quot;dojo&quot; /> Want to use dojo 0.9? Just use CDN: <script type=&quot;text/javascript&quot; djConfig=&quot;isDebug: true&quot; src=&quot;http://o.aolcdn.com/dojo/0.9.0/dojo/dojo.xd.js&quot;></script> <script type=&quot;text/javascript&quot;> dojo.addOnLoad(function(){ alert('loaded, all good'); }); </script>
  • 7. Understanding Grails & AJAX What a surprise, Grails can serve JavaScript, too! Grails supports AJAX with special tags that provide basic AJAX support for these libraries: prototype, Yahoo! UI, Dojo Abstraction Layer Dojo currently has to be installed separately, Y UI and Prototype come with.
  • 8. Dojo is more than AJAX Many say AJAX but really mean AJAX + Widgets. Dojo is very strong in Widgets. Besides this, you get way more: package system, animations, utilities, ShrinkSafe… But: you have to code this in your own code, in javascript. No tags can help you here.
  • 9. Learning Path Get familiar with Grails Use some Grails AJAX Tags in your pages, see what source code they generate Experiment with your own Javascript / Dojo code Really understand JavaScript & CSS
  • 11.  
  • 12. remoteLink Creates an <a> Link, submits the request via AJAX and is capable of replacing a div upon response. Several onXXX Methods to customize the call. <div id=&quot;message&quot;></div> <g:remoteLink action=&quot;remoteLinkCallId&quot; id=&quot;1&quot; update=&quot;message&quot;> AJAX Call, id=1 </g:remoteLink> def remoteLinkCallId = { log.debug(&quot;${actionName} Action called with ${params.id}&quot;) render &quot;You called ${actionName} in ${controllerName} with ${params.id}&quot; }
  • 13. formRemote Creates a <form> that will submit all input fields via AJAX. <g:formRemote url=&quot;[action:'formRemoteCall']&quot; name=&quot;form2&quot; update=&quot;message&quot; onLoading=&quot;toggleSpinner(true)&quot; onLoaded=&quot;toggleSpinner(false)&quot; > User: <input name=&quot;user&quot; type=&quot;text&quot;></input> <input type=&quot;submit&quot; value=&quot;formRemote Call&quot;></input> </g:formRemote> def formRemoteCall = { log.debug(&quot;${actionName} Action called with ${params.user}&quot;) render &quot;You called ${actionName} in ${controllerName} with ${params.user}&quot; }
  • 14. submitToRemote Same as formRemote, just the submit logic is executed on a specific submit button, not all submit buttons. <g:javascript library=&quot;dojo&quot; /> <g:javascript> dojo.require(&quot;dojo.io.IframeIO&quot;); </g:javascript> <g:form url=&quot;[action:'submitToRemoteCall']&quot; id=&quot;form2&quot; enctype=&quot;multipart/form-data&quot;> File: <input name=&quot;someFile&quot; type=&quot;file&quot;></input> <g:submitToRemote value=&quot;Submit Upload&quot; name=&quot;form2&quot; action=&quot;submitToRemoteUpload&quot; update=&quot;[success:'message',failure:'error']&quot; /> </g:form>
  • 15. submitToRemote Form uploads require us to send the response in an HTML textarea field! def submitToRemoteUpload = { def f = request.getFile('someFile') if(f.empty) { render &quot;No file!&quot; } else { def fileName = f.getOriginalFilename() render(text:&quot;<html><body><textarea>You called ${actionName} in ${controllerName} with file ${fileName}</textarea></body></html>&quot;, contentType:&quot;text/html&quot;, encoding:&quot;UTF-8&quot;) } }
  • 16. remoteField Creates an <input> field that submits itself automatically <g:remoteField before=&quot;if (this.value.length < 3) return false;&quot; action=&quot;quickSearch&quot; update=&quot;tableContent&quot; name=&quot;search&quot; paramName=&quot;search&quot;/> <span id=&quot;spinner&quot; style=&quot;display:none;&quot;> <img src=&quot;${createLinkTo(dir:'images',file:'spinner_mac.gif')}&quot; alt=&quot;Spinner&quot; /> </span> def quickSearch = { def devices = Device.findAllByModelLike(&quot;%${params.search}%&quot;, [max:20, sort :&quot;model&quot;, order:'asc']) render(template:'tableContent', model:[deviceList:devices]) }
  • 17. remoteField list.gsp <table> <thead> <tr> ... </tr> </thead> <tbody id=&quot;tableContent&quot;> <g:each in=&quot;${deviceList}&quot; var=&quot;device&quot;> ... </g:each> </tbody> </table> _tableContent.gsp <g:each in=&quot;${deviceList}&quot; var=&quot;device&quot;> <tr> <td>${device.id}</td> ... </tr> </g:each>
  • 19. Grails AJAX Tags Basic AJAX functionality, good to get started or for very easy use cases More complex stuff: master dojo define the content you send yourself 0.9 Complex UI changes
  • 20. Grails AJAX Tags do not provide Support for Dijit Widgets … but Grails is the ideal server part for many data-hungry widgets – next section.
  • 22. Render() is your best friend Whether you render pure text, html or JSON/XML formatted text, render() does it all. Creating simple responses is quick and easy: render &quot;This is easy.“ render &quot;{font:{id:10, name:'Arial'}}&quot; If you got larger, more complex responses, use a template to keep it clean: render(template:'podcastList', model:[podcasts:Podcast. findAll ()])
  • 23. Rendering JSON JSON is faster than XML, it should be AJAJ XML is evil, don’t use it Really, guess what’s faster: <?xml version=&quot;1.0&quot; encoding=&quot;ISO-8859-1&quot;?><linked-hash-map> <entry> <string>identifier</string> <string>id</string> </entry> <entry> <string>items</string> <list> <linked-hash-map> <entry> <string>id</string> <long>1</long> </entry> <entry> <string>url</string> <string>http://url1/rss</string> </entry> </linked-hash-map> <linked-hash-map> <entry> <string>id</string> <long>2</long> </entry> <entry> <string>url</string> <string>http://url2/rss</string> </entry> </linked-hash-map> <linked-hash-map> <entry> <string>id</string> <long>3</long> </entry> <entry> <string>url</string> <string>http://url3/rss</string> </entry> </linked-hash-map> <linked-hash-map> <entry> <string>id</string> <long>4</long> </entry> <entry> <string>url</string> <string>http://url4/rss</string> </entry> </linked-hash-map> <linked-hash-map> <entry> <string>id</string> <long>5</long> </entry> <entry> <string>url</string> <string>http://url5/rss</string> </entry> </linked-hash-map> <linked-hash-map> <entry> <string>id</string> <long>6</long> </entry> <entry> <string>url</string> <string>http://url6/rss</string> </entry> </linked-hash-map> <linked-hash-map> <entry> <string>id</string> <long>7</long> </entry> <entry> <string>url</string> <string>http://url7/rss</string> </entry> </linked-hash-map> <linked-hash-map> <entry> <string>id</string> <long>8</long> </entry> <entry> <string>url</string> <string>http://url8/rss</string> </entry> </linked-hash-map> <linked-hash-map> <entry> <string>id</string> <long>9</long> </entry> <entry> <string>url</string> <string>http://url9/rss</string> </entry> </linked-hash-map> <linked-hash-map> <entry> <string>id</string> <long>10</long> </entry> <entry> <string>url</string> <string>http://url10/rss</string> </entry> </linked-hash-map> </list> </entry> </linked-hash-map> {&quot;identifier&quot;:&quot;id&quot;,&quot;items&quot;:[{&quot;id&quot;:1,&quot;url&quot;:&quot;http://url1/rss&quot;},{&quot;id&quot;:2,&quot;url&quot;:&quot;http://url2/rss&quot;},{&quot;id&quot;:3,&quot;url&quot;:&quot;http://url3/rss&quot;},{&quot;id&quot;:4,&quot;url&quot;:&quot;http://url4/rss&quot;},{&quot;id&quot;:5,&quot;url&quot;:&quot;http://url5/rss&quot;},{&quot;id&quot;:6,&quot;url&quot;:&quot;http://url6/rss&quot;},{&quot;id&quot;:7,&quot;url&quot;:&quot;http://url7/rss&quot;},{&quot;id&quot;:8,&quot;url&quot;:&quot;http://url8/rss&quot;},{&quot;id&quot;:9,&quot;url&quot;:&quot;http://url9/rss&quot;},{&quot;id&quot;:10,&quot;url&quot;:&quot;http://url10/rss&quot;}]} XML or JSON?
  • 24. JSON is easy to read, too { &quot;identifier&quot;:&quot;id&quot;, &quot;items&quot;: [ { &quot;id&quot;:1, &quot;url&quot;:&quot;http://url1/rss&quot; }, { &quot;id&quot;:2, &quot;url&quot;:&quot;http://url2/rss&quot; }, { &quot;id&quot;:3, &quot;url&quot;:&quot;http://url3/rss&quot; }, { &quot;id&quot;:4, &quot;url&quot;:&quot;http://url4/rss&quot; } ] }
  • 25. JSON is easy to create, too Then work with it in you app: render(builder:'json') { element(imagePath: &quot; /app/myimage.png&quot;) } {&quot;element&quot;:{&quot;imagePath&quot;:&quot;/app/myimage.png&quot;}} dojo.io.iframe.send( { url: &quot;/some/url&quot;, form: dojo.byId('formImage'), handleAs: &quot; json &quot;, method: &quot;POST&quot;, handle: function(response, ioArgs) { var fileName = response.elementImage.fileName; } });
  • 26. Using converter & Render Converts domain objects to JSON import grails.converters.JSON def podcastJSON = { def podcast = Podcast.get(1) render podcast as JSON } { &quot;id&quot;:1, &quot;class&quot;:&quot;Podcast&quot;, &quot;author&quot;:&quot;Author1&quot;, &quot;feedURL&quot;:&quot;http://url1/rss&quot; }
  • 28. Data-hungry widgets ComboBox Provides a list of acceptable values but user can still enter his own value. Has a value, just like a textbox. FilteringSelect Much like ComboBox, but has label/value like a select. Will set ‘identifier’ as value of selected label. Tree
  • 29. Dojo ComboBox & Grails GSP <div dojoType=&quot;dojo.data.ItemFileReadStore&quot; jsId=&quot;stateStore&quot; url=&quot;<g:createLink controller=&quot;widget&quot; action=&quot;comboboxConverterData“ />&quot;> </div> <input dojoType=&quot;dijit.form.ComboBox&quot; store=&quot;stateStore&quot; hasDownArrow=&quot;false&quot; value=&quot;&quot; searchAttr=&quot;url&quot; name=“feed&quot; onChange=&quot;setValue&quot; />
  • 30. Dojo ComboBox & Grails Grails Action def comboboxConverterData = { def items = [] def podcasts = Podcast.findAll(); podcasts.each { podcast -> items << [id:podcast.id, url:podcast.feedURL] } def json = [identifier:&quot;id&quot;, items: items] render json as JSON } Using the Grails Converter simplifies the creation of the expected json structure.
  • 31. Dojo FilterSelect & Grails GSP <div dojoType=&quot;dojo.data.ItemFileReadStore&quot; jsId=&quot;feedStore&quot; url=&quot;<g:createLink controller=&quot;widget&quot; action=&quot;filterSelectData&quot; />&quot;> </div> <input dojoType=&quot;dijit.form.FilteringSelect&quot; id=&quot;chooser&quot; store=&quot;feedStore&quot; searchAttr=&quot;url&quot; name=&quot;feed&quot; autocomplete=&quot;true&quot; pageSize=&quot;5&quot; />
  • 32. Dojo FilterSelect & Grails Grails Action – the same…but! def filterSelectData = { def items = [] def podcasts = Podcast.findAll(); podcasts.each { podcast -> items << [id:podcast.id, url:podcast.feedURL] } def json = [identifier:&quot;id&quot;, items: items] render json as JSON } Once the user has chosen a label from the list, the identifier (here: podcast.id value) will be used as the value of the widget.
  • 33. Dojo Tree & Grails GSP <div dojoType=&quot;dojo.data.ItemFileReadStore&quot; jsId=&quot;treeStore&quot; url=&quot;<g:createLink controller=&quot;widget&quot; action=&quot;treeData&quot; />&quot;> </div> <div dojoType=&quot;dijit.Tree&quot; store=&quot;treeStore&quot; childrenAttr=&quot;children&quot; labelAttr=&quot;url&quot;> </div>
  • 34. Dojo Tree & Grails Grails Action def treeData = { def items = [] def children = [] (1..3).each { children << [_reference:&quot;${it}&quot;] } def podcasts = Podcast.findAll(); podcasts.each { podcast -> items << [id:podcast.id, url:podcast.feedURL, children:children ] } def json = [ identifier:&quot;id&quot; , label:'url', items: items] render json as JSON }
  • 36. Resources Download Dojo, check the test directories for tons of examples Dojo API Tool soon available for 0.9 http://www.dojotoolkit.org/api Converters Plugin http://www.grails.org/Converters+Plugin Dynamic Controller Methods, incl. render() grails.org/Controller+Dynamic+Methods
  • 37. Resources JSON Formatter http://www.curiousconcept.com/jsonformatter Blogs blogs blogs Grails Podcast http://hansamann.podspot.de/rss
  • 38. THX Y IM/SKYPE hansamann