Writing AngularJS applications in Groovy
AngularJS has taken the world by storm. Nobody can deny that.
Angular's declarative approach allows developers and designers alike to work closely together, designers creating the layouts and style of the pages with pure HTML and CSS, and developers adding the functionality of the page with directives.
But for a Java guy like me, there is one itch, and that is, when using AngularJS I have to use Javascript. Don't get me wrong, Javascript works great for small things and prototypes but once the code base grows most Javascript codebases turn into a mess. To remedy this there already exists Javascript frameworks to "fix" this, Coffeescript being one, but for most of them the tooling and IDE support is lacking in big ways, meaning you wont get much done with them. At least not quickly.
So what alternative do we have?
If we were Java purists we could turn to GWT (Google Web Toolkit) and wrap AngularJS like Ray Cromwell has done here (https://github.com/cromwellian/angulargwt).
But there is also another option, and that is using Groovy to write the applications with. With Groovy you can use the dynamic features of the language where it makes most sense and static typing where it is needed.
Curious how that can be achieved? Lets have a look.
Enter Grooscript (http://grooscript.org)
As you probably guessed Grooscript is a Groovy-to-Javascript compiler which will transform your Groovy code into pure Javascript. The first stable 1.0.0 was just released and it is working really great. It is still early days for the project of course but the potential there is huge.
But lets have a look at how we could utilize the Grooscript compiler to create our AngularJS application.
Select your build tool - Gradle
Since we are working with Groovy the natural choice is using Gradle for creating the project. There exists a great Gradle plugin for Grooscript at https://github.com/chiquitinxx/grooscript-gradle-plugin which we can use. It will add handy tasks for creating a project and compiling on the fly our Groovy to Javascript.
Here is an example build.gradle you can use
//build.gradle
plugins {
id "org.grooscript.conversion" version "1.0.0"
}
apply plugin: 'idea'
apply plugin: 'groovy'
repositories {
mavenCentral()
}
dependencies {
compile group: 'org.codehaus.groovy', name: 'groovy', version: '2.4.0'
compile ('org.grooscript:grooscript:1.0.0') {
exclude module: 'groovy'
}
}
grooscript {
destination = 'src/main/webapp/js/app'
classPath = ['src/main/groovy']
source = ['src/main/groovy/']
initialText = '// File generated by Grooscript'
}
Once you have that in a folder you can run gradle tasks to see what tasks Grooscript provides.
Grooscript tasks
----------------
convert - Convert groovy changes to javascript changes.
daemon - Launch grooscript conversion daemon. Block main thread and converting until killed.
initStaticWeb - Init static web project.
spyChanges - Listen changes in files and send notifications.
syncGsLibs - Syncronize grooscript libraries (grooscript.js, grooscript.min.js and grooscript-tools.js) with grooscript plugin version.
templatesJs - Generate templates js file.
templatesThread - Launch templates templates thread. Main thread continues.
thread - Start a conversion daemon in a thread. Main thread continues.
The task we want to use to start with is the initStaticWeb task which will create the folder structure for us. Run that and you will get the following folder structure:
├── build.gradle
└── src
└── main
├── groovy
│ └── Presenter.groovy
└── webapp
├── index.html
└── js
├── app
└── lib
├── grooscript.min.js
├── grooscript-tools.js
└── jquery.min.js
As you can see the task will download the necessary libraries and create the basic folder structure. It will also add an example Presenter that uses jquery. Now lets modify the project a bit to use Angular instead.
Using AngularJS with Grooscript
We start by removing the presenter and jquery library as we are not going to need them and instead add angular to the lib directory. Of course you could use something like Bower to manage the lib directory but lets keep it simple for now and just do it manually. You can get the needed AngularJS Javascript files form https://code.angularjs.org/1.3.11/
Also add four empty Groovy files (AngularModule.groovy, Application.groovy, Controllers.groovy and Services.groovy) to your source folder. We will implement them later.
Finally, lets add some views to our application by adding three html files named home.html, view1.html, view2.html into the webapp/html subfolder. We will add the content to them later.
The project should now look roughly like this:
├── build.gradle
└── src
└── main
├── groovy
│ └── AngularModule.groovy
│ ├── Application.groovy
│ ├── Controllers.groovy
│ └── Services.groovy
└── webapp
├── html
│ ├── home.html
│ ├── view1.html
│ └── view2.html
├── index.html
└── js
├── app
└── lib
├── angular.min.js
├── angular-resource.min.js
├── angular-route.min.js
├── grooscript.min.js
└── grooscript-tools.js
Now, we have all the files we need.
Next, lets put on the Designer hat and create the application in HTML only. Here are the contents of the HTML files:
index.html
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title>My Groovy Angular App!</title>
<!-- Grooscript libraries -->
<script type="text/javascript" src="js/lib/grooscript.min.js"></script>
<script type="text/javascript" src="js/lib/grooscript-tools.js"></script>
<!-- Angular libraries -->
<script type="text/javascript" src="js/lib/angular.min.js"></script>
<script type="text/javascript" src="js/lib/angular-resource.min.js"></script>
<script type="text/javascript" src="js/lib/angular-route.min.js"></script>
<!-- Application libraries -->
<script src="js/app/AngularModule.js"></script>
<script src="js/app/Services.js"></script>
<script src="js/app/Controllers.js"></script>
<script src="js/app/Application.js"></script>
</head>
<body>
<main ng-view>Main view placeholder</main>
<!-- Initialize the application -->
<script type="text/javascript">
new Services().init()
new Controllers().init()
new Application().init()
</script>
</body>
</html>
home.html
<h1>Hello AngularJS</h1>
<div ng-controller="TimeController">
The current time is: <b ng-bind="time.date"></b> <span ng-bind="time.time"></span>
</div>
<h3>Subpages</h3>
<ul>
<li><a href="#view1">View 1</a></li>
<li><a href="#view2">View 2</a></li>
</ul>
view1.html
<h2>This is View 1</h2>
view2.html
<h2>This is View 2</h2>
As you can see it is a simple application with a couple of views.
Next we switch hats and take the role of the developer who is tasked to make the application work. Here are the groovy implementations:
AngularModule.groovy
import org.grooscript.asts.GsNative
trait AngularModule {
// Returns the angular JS native instance
@GsNative getAngular(){/* return window.angular; */}
}
Services.groovy
class Services implements AngularModule {
def init() {
// Create services module
def services = angular.module('myAppServices', ['ngResource'])
// Create Time service
services.factory('TimeService', { $resource ->
$resource('http://date.jsontest.com/')
})
}
}
Controllers.groovy
class Controllers implements AngularModule {
def init() {
// Create the controllers module
def controllers = angular.module('myAppControllers', ['myAppServices'])
// Create time controller with injected scope and time service
controllers.controller('TimeController', { $scope, TimeService ->
// Get time from time service
$scope.time = TimeService.get()
})
}
}
Application.groovy
class Application implements AngularModule {
def init(){
// Create application module
def app = angular.module('myApp', ['myAppControllers', 'ngRoute'])
// Create routes
app.config { $routeProvider, $locationProvider ->
$routeProvider.when('/', [
templateUrl: 'html/home.html'
]).when('/view1', [
templateUrl: 'html/view1.html'
]).when('/view2', [
templateUrl: 'html/view2.html'
]).otherwise({
redirectTo: '/'
});
}
}
}
Compiling into Javascript
Now that we have the application ready all that remains is converting the Groovy into javascript. To do that the Grooscript Gradle plugin has a couple of handy tasks.
For a one time compilation just run the convert task and all the Javascript will be compiled into the webapp/js/app folder. This task is useful when you are compiling the final version with a CI server for example.
While developing a more useful task is the deamon task. It compiles the Groovy files on the fly whenever you make a change making the round-trip time from changing something in the Groovy class to viewing it in the browser minimal.
Once you compiled the Groovy files just load the index.html in your preferred browser and you are good to go!
Conclusion
And there you have it. Using Groovy with AngularJS. I think it is a really cool feature and combining it with build tools like Gradle and IDE's like Intellij Idea which has excellent Groovy and Gradle support makes it really an unbeatable combination.
The sources for this article can also be found over at https://github.com/johndevs/groovy-angularjs.
What do you think? Better than pure Javascript?