AngularJS Grails Template - Part 1: Getting Started
The goal of the Angular Grails Lazybones Project was to create a simple starting point for people who wanted to use AngularJS and Grails together. This allows you to setup an Grails project and generate AngularJS CRUD applications from your domain classes.
Creating a New Project
First we need to make sure we have lazybones installed. The easiest way to do this is through GVM like so:
Then we can easily create our new web app:
After running this command you’ll be asked a series of questions about your project. Here’s what the questions look like, with responses I’ve entered for an example application:
1
2
3
4
5
6
Define the name for your project [angular-grails]: example-app
Defined the version of AngularJS you want in your project [1.3]: 1.3
Define value for your main AngularJS module [myApp]: exampleApp
Define the value for your application group [com.company]: com.craigburke
Define value for your application 'version' [0.1]: 1.0
Define the name for your war file [ROOT.war]: my-app.war
When selecting the AngularJS version (question 2), you can opt for either AngularJS 1.2 or 1.3. If you need to support an older version of Internet Explorer(IE) such as IE 8 or below, you should choose AngularJS 1.2. The 1.3 version does not support IE 8 and below.
After answering these questions you should then have a new Grails project in the folder you specified (example-app in this case) with some goodies like Bootstrap, Angular UI and Font Awesome already included. As we’ll see later, there’s also a lazybones subtemplate (located in the .lazybones folder) that will help you create new Angular modules.
One other way that this project is different from a standard Grails project is that it makes use of Grails Gradle plugin.
By using the Gradle Grails plugin here we can run JavaScript and Groovy tests with a single command and also not have to worry about installing all the testing dependencies that are needed (Karma, Jasmine, PhantomJS, etc).
Adding a Domain Class
Once we’ve created our project, the next step is to add a domain class in the usual grails-app/domain location. Here’s an Employee domain class I’ll use for this example:
grails-app/domain/com/craigburke/Employee.groovy
Generating a CRUD AngularJS Module
Now that we have the domain class to use as our base, we can generate an AngularJS CRUD module to get us started by running the following with the project folder:
We’ll then be prompted to answer some questions about our new module:
Now we can run our app to take a look at our new module
If we browse to http://localhost:8080/example-app/employee we should see something like this:
We’ve got a paged list of employees that we can add to (as well as edit and delete), we can also filter the list on based on the four properties found in the domain class. Awesome!
Project stucture
Next we’ll take a look at exactly what the lazybones generate command actually added to our project. First lets take a look at the relevant parts of our grails-app/conf/UrlMappings.groovy file:
Here we see that two mappings have been created one for the REST actions /api/employee and one that links to a new view that was created.
Now we’ll look at the EmployeeController that was generated which handles all those REST requests:
grails-app/controllers/com/craigburke/EmployeeController.groovy
The PagedRestfulController is very similar to the default RestfulController that’s part of Grails with some additional support for filtering and paging.
Here’s what the employee.gsp view looks like:
grails-app/views/employee.gsp
This view is very simple because it’s just the entry point of our AngularJS app. All the relevant JavaScript and angular templates are found in /grails-app/assets/javascripts/example-app/employee. Here’s what the structure of our new AngularJS module looks like:
Tests
The lazybones generate command also added some tests for our new module. There are Geb/Spock functional tests as well as AngularJS Jasmine unit tests as seen below:
This tests may fail depending on your specific constraints, but should serve as a good starting point. To run all the tests you use this command:
If you want to run only the Jasmine unit tests you can run this command:
Alternatively you can run your Jasmine tests in watch mode so they are run everytime your source changes:
These Gradle tasks are setup so that all the dependencies are downloaded and resolved for you. The only thing you need to have install is the JDK.
Paging and Filtering
The default filtering works well for simple cases but you’ll likely want to override this method to have a bit more control over what is filtered.
For example if I wanted to add just a simple box that searches both first name and last name I would override the loadPagedResults method in my EmployeeController like so:
grails-app/controllers/com/craigburke/EmployeeController.groovy
The relevant part of the HTML in my /grails-app/assets/javascripts/example-app/employee/templates/list.tpl.html file would then be simplified to this:
JSON Response
When you generate a new CRUD module, a custom JSON marshaller is created for your domain class and added to to the CustomMarshallerRegistrar class.
Here’s an example of what the default marshaller for the Employee class would look like:
src/groovy/com/craigburke/CustomMarshallerRegistrar.groovy
By default it includes all the fields from the Employee domain class in addition to a toText property that is set to the value of the toString method.
If, for example, you wanted to remove salary property from the default JSON response, just remove that line from here. This will mean though, that you’ll need to modify your Angular Templates to remove the references to salary as well. In this case, the templates would be located within the grails-app/assets/javascripts/example-app/employee/templates folder.
Conclusion
As you can see, this template allows you to quickly get started building an AngularJS application in Grails.
The template was designed to be highly customizable and there are lots of ways to customize and modify your app and the modules you can generate. I go into more detail on the more advanced customization in Part 2: Advanced Customization.