A first taste of AngularJS

nicolas.chabanoles's picture
Article submitted by nicolas.chabanoles Mon, 06/30/2014 - 12:01

Like many developers around the planet, I heard about AngularJS. Haven't you?
I was willing to get a better understanding of what it is and what it could bring to my team.

As you may know, Bonita BPM Portal is currently developed with GWT and JQuery. We are working in a full java stack.

The tools we are using are JAVA, GWT, Maven and Eclipse but we are open to using new technologies, as long as they can bring benefits to the team. So why not have a look at AngularJS?

This blog post might be the first in a series, sharing our journey of discovery about this universe new to us: AngularJS.

Where’s a good place to start from?

Let’s go to the official web site https://angularjs.org/
The tutorials and the documentation give you an overview of what AngularJS is all about: "HTML enhanced for web apps!", "The ... environment is extraordinarily expressive, readable, and quick to develop." I found Codeschool to be a good resource for free tutorials: 
https://www.codeschool.com/courses/shaping-up-with-angular-js

Last but not least, I found the book " Mastering Web Application Development with AngularJS " by Peter Bacon Darwin and Pawel Kozlowski, to be the most useful resource when starting with AngularJS. The book presents all the concepts of AngularJS from a very pragmatic approach and illustrated with real life examples.

With all these resources read, I felt ready and very excited to start implementing my first AngularJS application, leveraging Bonita BPM 6 REST APIs!

Handle Bonita BPM REST API authentication

In order to be able to use Bonita BPM Rest API, you will need to provide a username and password. See the authentication section in the official documentation for the details: 
http://documentation.bonitasoft.com/web-rest-api-details-0#auth

main.js
  1. 'use strict';
  2.  
  3. /* Main Module declaration */
  4.  
  5. angular.module('BonitaBPM6Portal', ['login'])
  6.  
  7. .value('loggedUser', {username: ''})
  8.  
  9. .controller('MainCtrl', ['$scope', '$http', 'loggedUser', function ($scope, $http, loggedUser) {
  10.  
  11. $scope.loggedUser=loggedUser;
  12.  
  13. $http({
  14. method: 'GET',
  15. url: 'bonita/API/system/session/unusedid'
  16. }).success(function (data) {
  17. $scope.loggedUser.username = data.user_name;
  18. });
  19.  
  20. $scope.isUserLogged = function () {
  21. return $scope.loggedUser.username.length > 0;
  22. }
  23.  
  24. }]);

The main.js script declares the AngularJS module, in which all the sub modules will be included. A global variable loggedUser is declared to host the information of the user currently logged in (if any). The controller 'MainCtrl',checks whether the user is already logged in and updates the scope accordingly.

login.js
  1. angular.module('login', []).controller('LoginCtrl', ['$scope', '$http', 'loggedUser', function ($scope, $http, loggedUser) {
  2.  
  3. $scope.login = function (username, password) {
  4.  
  5. $http({
  6. method: 'POST',
  7. headers: {'Content-Type': 'application/x-www-form-urlencoded'},
  8. url: '/loginservice',
  9. transformRequest: function (obj) {
  10. var str = [];
  11. for (var p in obj)
  12. str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
  13. return str.join("&");
  14. },
  15. data: {username: username, password: password, redirect: 'false'}
  16. }).success(function (data, status, headers, config) {
  17. loggedUser.username = username;
  18. });
  19.  
  20. }
  21. }]);

The login.js script exposes a login (username and password) function to the scope. This method makes a server call to post credentials information and authenticates the user. If successful, the 'loggedUser' global variable is updated to store the identity of the user. Otherwise the visitor remains un-authenticated.

login-tpl.html
  1. <div class="container" ng-controller="LoginCtrl">
  2. <form class="form-signin" role="form" name="loginForm">
  3. <h2 class="form-signin-heading">Bonita BPM 6</h2>
  4. <input type="text" class="form-control span5" placeholder="Username" required="*" autofocus="" ng-model="login.username">
  5. <input type="password" class="form-control span5" placeholder="Password" required="*" ng-model="login.password">
  6. <button class="btn btn-lg btn-primary btn-block span5" ng-click="login(login.username, login.password)">Sign in</button>
  7. </form>
  8. </div>

The HTML fragment (partial) in 'login-tpl.html' describes a login box form. This is what our visitor will see if they are not authenticated. The form asks for a username and password. When the visitor hits the 'sign in' button, the login (username and password) method is called on the visible scope.

index.html
  1. <!doctype html>
  2.  
  3. <html lang="en" ng-app="BonitaBPM6Portal">
  4. <head>
  5. <meta charset="utf-8">
  6. <title>Bonita BPM Portal</title>
  7. <link rel="stylesheet" href="less/app.css" />
  8. </head>
  9.  
  10. <body ng-controller="MainCtrl">
  11.  
  12. <div class="container-fluid">
  13. <div ng-if="!isUserLogged()"><div ng-include="'app/login/login-tpl.html'"></div> </div>
  14. <div ng-if="isUserLogged()"><div class="alert alert-success" role="alert"><strong>Welcome:</strong> {{ loggedUser.username }}</div></div>
  15. </div>
  16.  
  17. <script src="assets/angular/angular.js"></script>
  18. <script src="app/main.js"></script>
  19. <script src="app/login/login.js"></script>
  20.  
  21. </body>
  22.  

The index.html file loads AngularJS and your application. While the visitor is not authenticated, a login form will be displayed inviting them to enter a username and password. Once the user is identified, the login form disappears and a welcome message is displayed on the page.

When running the application, the visitor will see a login box.

Login Form

The visitor can be authenticated using a valid username and password.

Form filled

Walter Bates can log in using his username and password: walter.bates / bpm

Logged in

Now we know how to authenticate on Bonita in a simple AngularJS application, we can build any page leveraging other Bonita REST APIs.

In conclusion, I found it easy to start working with AngularJS. The fact that the templating is based on the HTML syntax makes it readable and straightforward.

The first taste of AngularJS is sweet! I want more! :-)

Stay tuned for further code examples, using AngularJS and Bonita BPM REST API.
Captain Bonita

PS: All comments are welcome. If by any chance you have already written an Angular Application using Bonita REST API, feel free to share your feedback.
Twitter: @chabanoles

Comments

Submitted by amendonca Tue, 07/01/2014 - 22:48

Hi Nicolas, thanks for the post, ver useful! But I have had an issue when trying to replicate your example. My bonita server is allocated in a server and my tests in my work machine, so I got:
XMLHttpRequest cannot load http://xxx.xxx.xxx.xxx:9097/bonita/API/system/session/unusedid. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://xxx.xxx.xxx.xxx' is therefore not allowed access.
How can you solve this ?

Thanks in advance!

Submitted by nicolas.chabanoles Wed, 07/02/2014 - 09:48

Hi,

By default Web browsers & Web servers do not allow to have Javascript (hence AngularJS) loaded from one server and querying another server (this is called Same Origin Policy).

The easiest is to have both Bonita and your Angular application loaded by the same web server (e.g. Tomcat).

Let me know if it solved your issue, Captain Bonita

Submitted by amendonca Wed, 07/02/2014 - 16:01

Hi Captain Bonita!
After some research I reached this conclusion too, but, if we are making "a new Bonita Portal" with HTML and AngularJS (of course css added), I think it's more suitable a distribute application (think in mobile for example). So, in this case, it's no possible to host Angular files in the same Tomcat server. In my research I've found that we can solve this adding this permission in Java files with a clausule "Access-Control-Allow-Origin *".
In Bonita, how can we (I, as a representative of my dev team) do this ?

Thanks again!

Submitted by nicolas.chabanoles Wed, 07/02/2014 - 17:22

Hi,

I do not see why serving the new Angular portal with the same Tomcat would be an issue, you just have to put your web application ressources under the webapps folder of Tomcat, but maybe I am missing something...

Anyway here is a good link to follow to workaround the same origin policy using CORS on tomcat: http://software.dzhuvinov.com/cors-filter-installation.html

What I did for development was to setup another server to publish my AngularJS application and make all REST API call to that server that acts as an HTTP proxy for all bonita/* queries to the tomcat server. This way I avoid the same-origin-policy.

Let me know if you have more questions, Captain Bonita

Submitted by amendonca Wed, 07/02/2014 - 19:23

Hello, you did not missed anything, maybe I did not put myself clear. It's not an issue to put Angular in the same Tomcat as Bonita, but rather this, it's not my intention in a real distributed system I thought about. Anyway you did what I thought after my research, a proxy to redirect my requisitions.

Thanks again! This is really very useful for anyone.

Cheers

Submitted by yoyo_200098 Thu, 07/10/2014 - 10:39

Hi,
If you know GWT and you like server centric concept, look zk framework.
AngularJs will be dead when WebComponent will be adopt by every browsers (soon).
Webcomponent is support by w3c and do the similar thing of angularjs. but its native for browser.
Webcomponent come from mozilla technologie, XBL (Xml Binding Language), introduce with XUL language, but for all browser.
XUL was the first meta languge for write real UI, bur only for Firefox...
WebComponent is in fact the new name of XBL2

Regard

Submitted by box Mon, 07/14/2014 - 08:34

It 's very useful.

Thanks for sharing.