RIP AngularJS! Oh Sorry, RIP $scope, ng-controller, DDO, jqLite and whatever you like in AngularJS

I am  Software Developer, specifically Java Developer, spending most of the time writing back-end part of the applications. I can write basic HTML/JavaScript/CSS stuff to get the things done when needed. I didn’t have much passion on HTML/JavaScript and neither I am good at web development. I just has good enough knowledge to get the front-end work done for my requirements. Whenever I find sometime I tried to experiment with some cool back-end technologies like SpringBoot or JavaEE7, I never spend my weekends learning any front-end technologies.

When I had to develop UI for my projects I preferred PrimeFaces or SpringMVC/Bootstrap and get it done. But this situation got changed when I found AngularJS!!

Once I started learning and doing AngularJS stuff, I feel its a lot of fun doing front-end development too. AngularJS made so many things easy to build front-end UI such as templating, routing, Ajax etc. I started reading and experimenting with AngularJS on weekends too. I bought couple of AngularJS books and started tinkering with IONIC framework(which depends on AngularJS) too for Mobile Development. Everything about AngularJS is looking great.

Last night I saw ng-europe conference videos on YouTube and I was shocked by seeing their AngularJS 2.0 plans. The bottom line of AngularJS 2.0 is “They are going to kill everything that I learned and familiar with like $scope, controllers, jqLite etc” and introducing “annotation madness” and borrowing features from Dart/TypeScript/AtScript whatever.

Simply put the relationship between AngularJS 1.0 to AngularJS 2.0 is same as Struts 1.0 to Struts 2.0. They are sharing the same name for branding purpose, except that everything looks different.

Let us take a step back and see what is good and what is bad in AngularJS 2.0 direction.

Adaptability:
I feel one of the reasons for AngularJS popularity is, it is easy to learn and use even for back-end developers. I am not feeling the same excitement after looking at AngularJS 2.0 annotated classes, cryptic attributes like (click)=”doSomething()”.

As a Java Developer my primary interest is in back-end stuff and I just need a tool to get the front-end stuff done without delving too much into HTML/JavaScript world and I find AngularJS 1.x is really great for my kind of people.

Now with this 2.0 changes for adopting next generation ECMAScript/Dart/AtScript/Whatever features, AngularJS is not seems easy to me like it used to be.

Ecosystem:
One best part of AngularJS is you can find hell lot of information in blogs, YouTube, books etc. Just search for AngularJS tutorials, I am sure you will get piles of blogs and videos showing how to developing end to end applications using AngularJS.

Many people invested so much time in learning AngularJS way of doing things, blogged about it. Many books published on AngularJS and many more books are on the way.

With the AngularJS 2.0 direction, all of this knowledge become legacy. Do you buy and read an AngularJS 1.x book which is going to become legacy content soon??!!

Lot of developers spend so much time and build open-source modules and published on www.ngmodules.org. What will be the future of these modules?? What the module authors should do now? Should they continue adding more features for a dead end project? Should they take a break and wait for 2.0 release and rewrite their whole module as per 2.0 way of doing things??

Developer Tools:
NetBeans/Intellij/Eclipse IDE developers might have spent good amount of time for adding support for AngularJS. Now they have to write another set of plugin(s) for AngularJS 2.0 support!! What about Yeoman angular-generator and jHipster??!!

Future of applications recently ported to AngularJS:
Many of the enthusiastic developers learned and loved AngularJS and convinced their managers to use AngularJS for their next big project. Even worse, you might have recently migrated one of your legacy project to AngularJS. What will be the future of these kind of applications? Should we again rewrite whole application using AngularJS 2.0 or stick to AngularJS 1.3 forever??

Consider my scenario.
We have an internal application with a small set of futures which is developed using Java/Spring/jQuery. We have plans to add lot of other features to this application. I spent lot of time convincing my fellow developers that AngularJS is better and get them out of their “jQuery comfort zone”.

After I showed few demos and explained a bunch of AngularJS features, my manager and team agreed to go with SpringBoot and AngularJS. Now how do I break this news to my manager and team? Should I go back and say “Whatever I explained you about AngularJS is going to be changed completely and I don’t know how it will be in AngularJS 2.0”?.

OMG, I am complaining a lot!! I know it’s open-source world. If you like it use it, otherwise move on. Some people even argue you can fork it and continue on AngularJS 1.x branch and we all know where that argument leads to.

Don’t get me wrong. I am not saying frameworks/libraries should not be evolved. For a major version a framework can break compatibility to some extent, but not to an extent where you just have to rewrite everything.

Conclusion:
AngularJS 1.x was great. But even before my organization’s evaluation cycle completes you broke the compatibility rule. I can’t confidently suggest AngularJS for my future project anymore.

On the bright side, AngularJS 2.0 might be a better framework than AngularJS 1.x if you look at it as a brand new framework (who knows!!). Hope AngularJS 2.0 will be great!!.

AngularJS: Different ways of using Array Filters

AngularJS provides filter feature which can be used to format input value or to filter an Array with the given matching input criteria. For example you can use ‘date’ filter to format a Date value into human readable Date representation like MM-DD-YYYY as {{dob | date}}.

On the other hand there are Array filtering feature which is very useful while filtering data from an Array of JavaScript objects. The Array filtering is very commonly used with a Table along with ng-repeat directive.

For example, we can have a list of Todos which we can display in a Table using ng-repeat tag. And we can have a text field to search todos which matches any one of the data properties of Todo object as follows:

$scope.todos = [
    {id: 1,title: 'Learn AngularJS', description: 'Learn AngularJS', done: true, date: new Date()}  ,
    {id: 2,title: 'Explore ui-router', description: 'Explore and use ui-router instead of ngRoute', done: true, date: new Date()}  ,
    {id: 3,title: 'Play with Restangular', description: 'Restangular seems better than $resource, have a look', done: false, date: new Date()}  ,
    {id: 4,title: 'Try yeoman', description: 'No more labour work..use Yeoman', done: false, date: new Date()}  ,
    {id: 5,title: 'Try MEANJS', description: 'Aah..MEANJS stack seems cool..why dont u try once', done: false, date: new Date()}                
            ];


<input type="text" ng-model="searchTodos">
 <table class="table table-striped table-bordered">
 <thead>
  <tr>
   <th>#</th>
   <th>Title</th>
   <th>Description</th>
   <th>Done?</th>
   <th>Date</th>
  </tr>
 </thead>
 <tbody>
  <tr ng-repeat="todo in todos| filter: searchTodos">
   <td>{{$index + 1}}</td>
   <td>{{todo.title}}</td>
   <td>{{todo.description}}</td> 
   <td>{{todo.done}}</td>
   <td>{{todo.date | date}}</td> 
  </tr>

 </tbody>

</table>

Observe that our search input field’s ng-model attribute is set to ‘searchTodos‘ which we have used to filter on ng-repeat attribute. As you type in the search input field, the $scope.todos array will be filtered and only matching records will be shown up. This is a “match anything” type filter, means the search criteria will be checked against all properties(id, title, description, date) of Todo object.

If you want to search only on one field, say ‘description‘, you can apply filter as follows:

<tr ng-repeat="todo in todos| filter: {description: searchTodos}">

If you want to display only Todos which aren’t done yet then you can do it as follows:

 
<tr ng-repeat="todo in todos| filter: {description: searchTodos, done: false}">

Note that here the 2 conditions will be applied using AND conditions. 

If you want to display only Todos which aren’t done yet and you want to search on all fields not just on ‘description‘ then you can do it as follows:

<tr ng-repeat="todo in todos| filter: {$: searchTodos, done: false}">

Here $ means all fields. So far so good as it is a simple and straight forward case.

How about having nested objects in our Array objects and we want to search based on a nested object property?

Let’s look at such a type of scenario. In order to explain these scenarios I am using some code examples from my ebuddy application.

In my ebuddy application I have an ExpenseManager module where I will keep track of my expenses as follows:

  • I will have a list of Accounts such as Cash, savings Bank Account, CreditCard etc with the current balance details.
  • I will have a list of Payees such as HouseRent, PowerBill, Salary etc which fall into INCOME or EXPENDITURE categories.
  • I will record all my transactions by picking one of the account and a Payee and the amount.

This application is just to record my financial transactions so that I can see monthly reports by Account or Payee wise. I hope you get an idea about the domain model.

Now let us create a simple AngularJS application and set some sample data.

  
<!DOCTYPE html>
 <html ng-app="myApp">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>My AngularJS App</title>
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet" type="text/css"/>
  <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.20/angular.min.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.2.0/js/bootstrap.min.js"></script>
  
  <script>
      var myApp = angular.module('myApp',[]);
      myApp.controller('SampleController', function($scope){
            $scope.accounts = [ 
                    {id: 1, name: 'Cash'}, 
                    {id: 2, name: 'Bank Savings'} 
                  ];
            $scope.payees = [
                    {id:'1',name:'HouseRent', txnType:'EXPENDITURE'},
                    {id: '2', name:'InternetBill', txnType:'EXPENDITURE'}, 
                    {id:'3', name: 'PowerBill', txnType:'EXPENDITURE'}, 
                    {id:'4', name: 'Salary', txnType:'INCOME'}
                  ];
            $scope.transactions = [
                {id:'1', txnType:'EXPENDITURE', amount: 1000, account: $scope.accounts[0], payee: $scope.payees[0]},
                {id:'2', txnType:'EXPENDITURE', amount: 500, account: $scope.accounts[1], payee: $scope.payees[1]},
                {id:'3', txnType:'EXPENDITURE', amount: 1200, account: $scope.accounts[0], payee: $scope.payees[1]},
                {id:'4', txnType:'INCOME', amount: 5000, account: $scope.accounts[1], payee: $scope.payees[3]},
                {id:'5', txnType:'EXPENDITURE', amount:200, account: $scope.accounts[0], payee: $scope.payees[2]}
            ];
            
      });
      
  </script>  
</head>
<body ng-controller="SampleController">
<br/>
 <div class="col-md-8 col-md-offset-2">
        
    <h3>Transaction Details</h3>
    <table class="table table-striped table-bordered">
        <thead>
            <tr>
                <th>#</th>
                <th>Account</th>
                <th>Type</th>
                <th>Payee</th>
                <th>Amount</th>
            </tr>
        </thead>
        <tbody>
            <tr ng-repeat="txn in transactions">
                <td>{{$index + 1}}</td>
                <td>{{txn.account.name}}</td>
                <td>{{txn.txnType}}</td> 
                <td>{{txn.payee.name}}</td> 
                <td>{{txn.amount}}</td> 
            </tr>
        </tbody>
    </table>
</div>

</body>
</html>

This is a very simple AngularJS page which is displaying list of transactions in a table. Observe that the transactions contains nested objects (account, payee) and we are displaying nested properties (txn.account.name, txn.payee.name) in our table.

Now we want to filter the transactions in a variety of ways, so lets look at them case by case.

Case#1: Search by Payee Name 
In our transaction object we have a nested payee object which contains name property on which we want to perform search.

Let us create form which will contain all our filters before transactions table.
The first thought that came to my mind to perform a search on a nested property is use the nested property path in filter as follows:

 
<input type="text" ng-model="payeeName">
...
<tr ng-repeat="txn in transactions| filter: {payee.name : payeeName}">

But THIS WON”T WORK. 

To search on a nested property we can name our input field ng-model to match the target property path and use the root object name as filter as follows:

 
<div class="col-md-8 col-md-offset-2">
     <form class="form-horizontal" role="form">
        <div class="form-group">
          <label for="input1" class="col-sm-4 control-label">Search by Payee</label>
          <div class="col-sm-6">
            <input type="text" class="form-control" id="input1" placeholder="Payee Name" ng-model="filterTxn.payee.name">
          </div>
        </div>
  <!-- additional filters will come here -->
 </form>
 <h3>Transaction Details</h3>
 <table class="table table-striped table-bordered">
  ...
  <tbody>
            <tr ng-repeat="txn in transactions| filter: filterTxn">
                ...
    ...
            </tr>
  </tbody>
 </table>
</div>

Observe that we have bind the input field ng-model to “filterTxn.payee.name” and used filter: filterTxn as filter. So txn.payee.name will be matched against filterTxn.payee.name.

Case#2: Filter by Accounts Dropdown 
We would like to filter the transactions by using Accounts Select dropdown. First we need to populate a select dropdown using $scope.accounts and use it as a filter.

Add the following filter after our first filter.

  
<div class="form-group">
  <label for="input2" class="col-sm-4 control-label">Search By Account</label>
  <div class="col-sm-6">
  <select id="input2" class="form-control" ng-model="filterTxn.account">
   <option value="">All Accounts</option>
   <option ng-repeat="item in accounts" value="{{item.id}}">{{item.name}}</option>
  </select>
  </div>
</div>

Here we are populating a <select> field with $scope.accounts array by displaying Account Name and using id as value.

The key part here is we have bind ng-model to filterTxn.account. When we select an account, the selected account object reference will be stored in filterTxn.account. As we already have filterTxn as filter, the account filter will also be applied along with payee name filter.

Also note that the first option “All Accounts” value is empty (“”) which will be treated as null by AngularJS, so when the “All Accounts” is option is selected no account filter will be applied.

Case#3: Search By Transaction Type 
We want to filter the transaction by transaction type (INCOME or EXPENDITURE):

Add the following filter after the second filter:

  
<div class="form-group">
  <label for="input3" class="col-sm-4 control-label">Search By Type</label>
  <div class="col-sm-6">
  <select id="input3" class="form-control" ng-model="filterTxn.txnType">
   <option value="">All Types</option>
   <option value="EXPENDITURE">EXPENDITURE</option>
   <option value="INCOME">INCOME</option>
  </select>
  </div>
</div>

I hope no further explanation is need for this 🙂

Case#4: Search by Payees of Expenditure type 
Aaah..this is interesting!!. We want to search by Payee names but only in EXPENDITURE type payees.

We can’t simply apply filter like “filter: expPayeeFilter | filter: {txnType: ‘EXPENDITURE’}” because it will always filter by EXPENDITURE.

So we will create a custom filter to perform “search by payee name in EXPENDITURE type payees only when some filter text entered” as follows:

  
myApp.filter('expenditurePayeeFilter', [function($filter) {
 return function(inputArray, searchCriteria, txnType){         
  if(!angular.isDefined(searchCriteria) || searchCriteria == ''){
   return inputArray;
  }         
  var data=[];
  angular.forEach(inputArray, function(item){             
   if(item.txnType == txnType){
    if(item.payee.name.toLowerCase().indexOf(searchCriteria.toLowerCase()) != -1){
     data.push(item);
    }
   }
  });      
  return data;
 };
}]);

We have created a custom filter using myApp.filter() and inside it we have used angular.forEach() to iterate over the input array, rest is plain javascript..no magic.

Now we will apply this custom filter as follows:

  
<tr ng-repeat="txn in transactions| filter: filterTxn | expenditurePayeeFilter:searchCriteria:'EXPENDITURE'">
 <td>{{$index + 1}}</td>
 <td>{{txn.account.name}}</td>
 <td>{{txn.txnType}}</td> 
 <td>{{txn.payee.name}}</td> 
 <td>{{txn.amount}}</td> 
</tr>

Observer the syntax: customFilterName:param1:param2:..:paramN.
These parameters will be passed as arguments to the function inside our custom directive.

We have seen few interesting options on how to use AngularJS array filtering features.

You can find the complete page at https://gist.github.com/sivaprasadreddy/fbee047803d14631fafd


Hope it helps. 🙂

AngularJS: Introducing modules, controllers, services

In my previous post AngularJS Tutorial: Getting Started with AngularJS we have seen how to setup an application using SpringBoot + AngularJS + WebJars. But it’s a kind of quick start tutorial where I haven’t explained much about AngularJS modules, controllers and services. Also it is a single screen (only one route) application.

In this part-2 tutorial, we will take a look at what are Angular modules, controllers and services and how to configure and use them. Also we will look into how to use ngRoute to build multi-screen application.

If we take a look at the code that we developed in previous post, especially in controllers.js, we clubbed the client side controller logic and business logic(of-course we don’t have any biz logic here :-)) in our Controllers which is not good.

As java developers we get used to have dozen layers and we love making things complex and complain Java is complex. But here in AngularJS things looks simpler, let’s make things little bit complex. I am just kidding 🙂

Even if you put all your logic in single place as we did in controllers.js, it will work and acceptable for simple applications. But if you are going to develop large enterprise application (who said enterprise applications should be large…hmm..ok..continue..) then things quickly become messy. And believe me working with a messy large JavaScript codebase is lot more painful than messy large Java codebase. So it is a good idea to separate the business logic from controller logic.

In AngularJS we can organize application logic into modules and make them work together using dependency injection. Lets see how to create a module in AngularJS.

var myModule = angular.module(‘moduleName’,[‘dependency1′,’dependency2’]);

This is how we can create a module by using angular.module() function by passing the module name and specifying a list of dependencies if there are any.

Once we define a module we can get handle of the module as follows:

var myModule = angular.module(‘moduleName’);

Observe that there is no second argument here which means we are getting the reference of a predefined angular module. If you include the second argument, which is an array, then it means you are defining the new module.

Once we define a new module we can create controllers in that module as follows:

module.controller(‘ControllerName’,[‘dependency1′,’dependency2’, function(dependency1, dependency2){
//logic
}]);

For example, lets see how we to create TodoController.

var myApp = angular.module(‘myApp’,[‘ngRoute’]);
myApp.controller(‘TodoController’,[‘$scope’,’$http’,function($scope,$http){
//logic
}]);

Here we are creating TodoController and providing $scope and $http as dependencies which are built-in angularjs services.

We can also create the same controller as follows:
myApp.controller(‘TodoController’,function($scope,$http){
//logic
});

Observe that we are directly passing a function as a second argument instead of an array which has an array of dependencies followed by a function which takes the same dependencies as arguments and it works exactly same as array based declaration.

But why do we need to do more typing when both do the same thing??

AngularJS injects the dependencies by name, that means when you define $http as a dependency then AngularJS looks for a registered service with name ‘$http‘. But majority of the real world applications use JavaScript code minification tools to reduce the size. Those tools may rename your variables to short variable names.

For example:
myApp.controller(‘TodoController’,function($scope,$http){
//logic
});

The preceding code might be minified into:
myApp.controller(‘TodoController’,function($s,$h){
//logic
});

Then AngularJS tries to look for registered services with names $s and $h instead of $scope and $http and eventually it will fail. To overcome this issue we define the names of services as string literals in array and specify the same names as function arguments. With this even after JavaScript minifies the function argument names, string literals remains same and AngularJS picks right services to inject.

That means you can write the controller as follows:

myApp.controller(‘TodoController’,[‘$scope’,’$http’,function($s,$h){
//here $s represents $scope and $h represents $http services
}]);

So always prefer to use array based dependencies approach.

Ok, now we know how to create controllers. Lets see how we can add some functionality to our controllers.

Here in our TodoController we defined a variable todos which initially holds an empty array and we defined loadTodos() function which loads todos from RESTful services using $http.get() and once response received we are setting the todos array to our todos variable. Simple and straight forward.

Why can’t we directly assign the response of $http.get() to our todos variable like todoCtrl.todos = $http.get(‘/todos.json’);??

Because $http.get(‘/todos.json’) returns a promise, not actual response data. So you have to get data from success handler function. Also note that if you want to perform any logic after receiving data from $http.get() you should put your logic inside success handler function only.

For example if you are deleting a Todo item and then reload the todos you should NOT do as follows:

$http.delete(‘/todos.json/1’).success(function(data){
//hurray, deleted
}).error(function(){
alert(‘Error in deleting Todo’);
});
todoCtrl.loadTodos();

Here you might assume that after delete is done it will loadTodos() and the deleted Todo item won’t show up, but that won’t work like that. You should do it as follows:

$http.delete(‘/todos.json/1’).success(function(data){
//hurray, deleted
todoCtrl.loadTodos();
}).error(function(){
alert(‘Error in deleting Todo’);
});

Lets move on to how to create AngularJS services. Creating services is also similar to controllers but AngularJS provides multiple ways for creating services.
There are 3 ways to create AngularJS services:

  • Using module.factory()
  • Using module.service()
  • Using module.provider()

Using module.factory()
We can create a service using module.factory() as follows:

Using module.service()
We can create a service using module.service() as follows:

Using module.provider()
We can create a service using module.provider() as follows:

You can find good documentation on which method is appropriate in which scenario at http://www.ng-newsletter.com/advent2013/#!/day/1.

Let us create a TodoService in our services.js file as follows:

Now inject our TodoService into our TodoController as follows:

Now we have separated our controller logic and business logic using AngularJS controllers and services and make them work together using Dependency Injection.

In the beginning of the post I said we will be developing a multi-screen application demonstrating ngRoute functionality.
In addition to Todos, let us add PhoneBook feature to our application where we can maintain list of contacts.

First, let us build the back-end functionality for PhoneBook REST services.

Create Person JPA entity, its Spring Data JPA repository and Controller.

Now let us create AngularJS service and controller for Contacts. Observe that we will be using module.service() approach this time.

Now we need to configure our application routes in app.js file.

Here we have configured our application routes on $routeProvider inside myApp.config() function.
When url matches with any of the routes then corresponding template content will be rendered in <div ng-view></div> div in our index.html.

If the url doesn’t match with any of the configured urls then it will be routed to ‘home‘ as specified in otherwise() configuration.

Our templates/home.html won’t have anything for now and templates/todos.html file will be same as home.html in previous post.

The new templates/contacts.html will just have a table listing contacts as follows:

Now let us create navigation links to Todos, Contacts pages in our index.html page <body>.

By now we have a multi-screen application and we understood how to use modules, controllers and services.
You can find the code for this article at https://github.com/sivaprasadreddy/angularjs-samples/tree/master/angularjs-series/angularjs-part2

Our next article would be on how to use $resource instead of $http to consume REST services. 
Also we will look update our application to use more powerful ui-router module instead of ngRoute. Stay tuned :-).

AngularJS Tutorial: Getting Started with AngularJS

AngularJS is a popular JavaScript framework for building Single Page Applications (SPAs).
AngularJS provides the following features which makes developing web apps easy:
1. Two way data binding
2. Dependency Injection
3. Custom HTML Directives
4. Easy integration with REST webservices using $http, $resource, Restangular etc
5. Support for Testing
and many more…

Though there are lot more features than the above mentioned list, these are the very commonly used features.

I am not going to explain what 2-way data binding is, how $scope works here because there are tons of material already on web.

As a Java developer, I will be using SpringBoot based RESTful back-end services. If you want you can use JavaEE/JAX-RS to build REST back-end services. Also you might like using NetBeans as it has wonderful AngularJS auto-completion support out of the box.

So lets get start coding AngularJS HelloWorld application.

Create index.html with the following content and start your server and point your browser to http://localhost:8080/hello-angularjs/index.html

Now start typing in input text and your Hello {{myname}} would immediately reflect the value you are entering in input text field.

Ok, we are done with “HelloWorld” ceremony and warm up :-).

We have used AngularJS CDN URL for loading AngularJS library. We can download AngularJS from https://angularjs.org/ add the angular.min.js script.

But we will be using WebJars (http://www.webjars.org/) which provides the popular javascript libraries as maven jar modules along with transitive dependencies. If we want to use Twitter Bootstrap we should include jQuery also. But using WebJars I need to configure only bootstrap jar dependency and it will pull jquery dependency for me.

Let us create a SpringBoot project by selecting File -> New -> Spring Starter Project, select “Web” and “Data JPA” modules and Finish.

If you are not using STS then you can create this starter template from http://start.spring.io/ and download it as zip.

We will be using Bootstrap and font-awesome javascript libraries to build our Web UI.
Lets configure H2 database, AngularJS, Bootstrap and font-awesome libraries as WebJar maven dependencies in pom.xml.

As it is a SpringBoot jar type application we will put all our html pages in src/main/resources/public folder and all our javascripts, css, images in src/main/resources/static folder.

  • Now modify the AngularJS CDN reference to <script src=”webjars/angularjs/1.2.19/angular.js”></script>.
  • Lets include the bootstrap and font-awesome css/js in our index.html. Also we will be using angular-route module for page navigation and hence we need to include angular-route.js as well.
  • Lets create app.js file which contains our main angularjs module configuration in src/main/resources/static/js folder.
  • Also create controllers.js, services.js, filters.js, directives.js in the same folder and include them in index.html.

SpringBoot will serve the static content from src/main/resources/static folder.

In Application.java file add the following RequestMapping to map context root to index.html.

Now run this Application.java as stand-alone class and go to http://localhost:8080/. It should work same as earlier.

Now we have basic setup ready. Lets build a very simple Todo application.

Create a JPA entity Todo.java, its Spring Data JPA repository interface and TodoController to perform Read/Create/Delete operations.

Create DatabasePopulator to setup some initial data.

Now our back-end RESTful web services ready at the following URLs.
GEThttp://localhost:8080/todos for getting list of Todos
POST http://localhost:8080/todos for creating new Todo
DELETE http://localhost:8080/todos/1 to delete Todo(id:1)

Lets create our main angularjs module ‘myApp‘ and configure our application routes in app.js file.

Now update index.html to hookup myApp module at the root of page using and use

to load the current route template.

Create home.html template in src/main/resources/public/templates folder.

It is a very simple html page with some bootstrap styles and we are using some angularjs features.
We are using ng-repeat directive to iterate through array of Todo JSON objects, ng-click directive to bind a callback function to button click.

To invoke REST services we will use angularjs built-in $http service. $http service resides in angular-route.js, don’t forget to include it in index.html.

$http.verb(‘URI’)
.success(success_callback_function(data, status, headers, config){
//use data
 })
.error(error_callback_function(data, status, headers, config) {
 alert(‘Error loading data’);
});

For example: to make GET /todos REST call

$http.get(‘todos’)
.success(function(data, status, headers, config) {
//use data
 })
.error(function(data, status, headers, config) {
 alert(‘Error loading data’);
});

Create TodoController in controllers.js file. In TodoController we will create functions to load/create/delete Todos.

Now point your browser to http://localhost:8080/. You should see list of Todos and New Todo Entry form and Delete option for each Todo item.

By now we get some hands-on with AngularJS basic features.
In next post I will explain using multiple routes, multiple controllers and services. Stay tuned 🙂

How to POST and GET JSON between EXTJS and SpringMVC3

After one month of evaluation of the frameworks and tools, i choose ExtJS for UI and Spring/SpringMVC for business layer for my pet project.

Again by using ExtJS we can send data to server by form submits or as request parameters or in json format through Ajax requests. ExtJS uses JSON format in many situations to hold data. So I thought using JSON as data exchange format between EXTJS and Spring will be consistent.

The following code snippets explains how we can use ExtJS and SpringMVC3 to exchange data in JSON format.

1. Register MappingJacksonHttpMessageConverter in dispatcher-servlet.xml

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">

<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
</list>
</property>
</bean>

Don’t forget to copy jackson-json jar(s) to WEB-INF/lib

2. Trigger the POST request from ExtJS script as follows:

Ext.Ajax.request({
url : 'doSomething.htm',
method: 'POST',
headers: { 'Content-Type': 'application/json' },
params : { "test" : "testParam" },
jsonData: {
"username" : "admin",
"emailId" : "admin@sivalabs.com"
},
success: function (response) {
var jsonResp = Ext.util.JSON.decode(response.responseText);
Ext.Msg.alert("Info","UserName from Server : "+jsonResp.username);
},
failure: function (response) {
var jsonResp = Ext.util.JSON.decode(response.responseText);
Ext.Msg.alert("Error",jsonResp.error);
}
});

3. Write a Spring Controller to handle the “/doSomething.htm” reguest.

@Controller
public class DataController
{
@RequestMapping(value = "/doSomething", method = RequestMethod.POST)
@ResponseBody
public User handle(@RequestBody User user) throws IOException
{
System.out.println("Username From Client : "+user.getUsername());
System.out.println("EmailId from Client : "+user.getEmailId());
user.setUsername("SivaPrasadReddy");
user.setEmailId("siva@sivalabs.com");
return user;
}
}

Any other better approaches?