Grails Angular Scaffolding
By James Kleeh, OCI Software Engineer
August 2016
INTRODUCTION
Creating a single-page application (SPA) has never been easier with the new Grails Angular Scaffolding Plugin! This article provides a short tutorial on how to use the plugin.
The easiest way to get started with scaffolding is to use the Angular profile in Grails 3.2.0 or higher, which installs and configures the plugin automatically. See the documentation for information on how to get the plugin installed into an existing application.
GRAILS QUICKCAST: ANGULAR SCAFFOLDING
OCI Engineer, James Kleeh, walks you through using the Angular Scaffolding for Grails to build a fully functional web app, using a simple blog format for demonstration. The tutorial explains how to have Grails set up a REST endpoint and all the Angular modules needed to get the web app running.
For this tutorial, we will be working with the following domain classes.
- package com.myblog
-
- import grails.rest.Resource
-
- @Resource(uri="/post")
- class Post {
- URL url
- PostContent postContent
- static embedded = ['postContent']
- static hasMany = [comments: Comment , tags: Tag]
- static constraints = {
- }
- }
- //---------------------------------
- package com.myblog
-
- class PostContent {
- String title
- String body
- Date published
- static constraints = {
- }
- }
- //---------------------------------
- package com.myblog
-
- import grails.rest.Resource
-
- @Resource(uri="/tag")
- class Tag {
- String name
- static constraints = {
- }
- }
- //---------------------------------
- package com.myblog
-
- import grails.rest.Resource
-
- @Resource(uri="/comment")
- class Comment {
- String text
- static belongsTo = [post: Post]
- static constraints = {
- }
- }
Generating Assets
Generating client-side assets with this plugin is very easy. In this example, the domain class you would like to have assets generated for is com.myblog.Post
:
grails ngGenerateAll com.myblog.Post
To specify, you wish any generated files to overwrite existing files:
grails ngGenerateAll com.myblog.Post true
You can also execute the same command with Gradle:
./gradlew ngGenerateAll -Pargs="com.myblog.Post true"
Some assets that are generated are common to all scaffolded modules. The scaffolding will generate those assets in the “core” module. The core module will be created in the same package as the module being generated if it doesn’t already exist. If a core module already exists, it will not be overwritten, even if the overwrite parameter is true.
The following structure will be produced:
Note that other modules were created along with the post module.
- A module for the
Comment
domain was created because the scaffolding will convert the list of comments to be instances of theComment
JavaScript domain. - The module for the
Tag
domain was also created by the scaffolding. The purpose of doing so is to facilitate retrieving a list of tags to choose from when creating aPost
.
The modules for the Tag
and Comment
domains do not provide CRUD functionality. They exist solely to assist the Post
module.
In the future, if you wish to scaffold the CRUD of Tag
s or Comment
s, execute the ngGenerateAll
command with the second parameter set to “true” so the existing assets will be overwritten.
Using the Assets
If you are using the Angular profile in Grails 3.2.0 or higher, none of the steps below are required because they are all done for you!
If you are working with an existing application, there are a few steps you must take to make everything work together as designed.
-
Ensure that the required third-party libraries exist where the scaffolding expects them to be.
The scaffolding requires angular, angular-resource, and ui-router to function as designed. The default locations for those assets are:
/angular/angular.js
/angular/angular-ui-router.js
/angular/angular-resource.js
You can change the default locations with configuration. See the asset paths section in the documentation to learn how to do so.
-
Ensure the required asset pipeline plugins have been imported.
The scaffolding is designed around the use of three asset pipeline plugins. Include the plugins in your project via the instructions in the links below.
Angular Annotate Asset Pipeline
-
Ensure databinding handles the default date format.
The scaffolding relies on the default format Angular applies to dates when they are included in a request. In Grails 3.1.x, the date format is not included in the default list of date formats that databinding will attempt to use. You can easily add it yourself via configuration.
grails:
databinding:
dateFormats:
- "yyyy-MM-dd'T'HH:mm:ss.SSSX"
-
Ensure the module is loaded on the page.
If the “parent” module is already required by your current code, there is nothing you need to do to get the newly generated module to be included wherever the parent module is. The scaffolding will automatically attempt to create a module dependency and require statement in the parent module. Here is an example of what that might look like:
grails ngGenerateAll com.myblog.Post
If
grails-app/assets/javascripts/com/myblog/com.myblog.js
exists, it will be considered the parent module. The scaffolding will attempt to edit the file to add a dependency to thepost
module.If a parent module does not exist, or the parent module isn’t being included on the desired page, it is up to you to use asset pipeline to include it where it is needed.
-
Ensure a
ui-view
directive is on the page for the state to load HTML into.See the ui-view documentation on how to do this.
-
Ensure the
ng-app
directive is on the page.ng-app="com.myblog.post"
-
Navigate to the route
http://localhost:8080/#post
CRUD
The following images depict what you will see when you have successfully navigated to the ‘post’ route and begin creating Post
s.
Note that clicking “Add Comment” at this time will not have any effect because the comment scaffolding has not been created.
Generating Associated Domains
The logical next step is to generate the Tag
scaffolding so we can create tags. This allows us to choose tags when creating or editing our Post
.
grails ngGenerateAll com.myblog.Tag true
Note that the second parameter “true” is important because we already had a Tag
module that we will need to overwrite in order for the scaffolding to function correctly.
In addition, we can generate the comment scaffolding to assign comments to posts.
grails ngGenerateAll com.myblog.Comment true
The following are screen captures of what you can expect once the associated domain classes are generated:
Tag
Comment
Conclusion
Now that all domain classes have scaffolding, you can manage your data in a SPA. The scaffolding is designed as a starting point for rapid development. Explore the generated JavaScript code and make changes to meet your business requirements. If you run into any issues, please submit an issue on the github page, or come chat with us about it in the Grails slack channel.
For a complete run through of installing and using the scaffolding in Grails 3.1.x, check out this quickcast!
The example project created in the video is available here.
Software Engineering Tech Trends (SETT) is a regular publication featuring emerging trends in software engineering.