Software Development

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

<html>
    <head>
        <title>Hello AngularJS</title>
        <meta charset="UTF-8">
        <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    </head>
    <body ng-app>
        <p>Enter Name: <input type="text" ng-model="myname"> </p>
        <p>Hello {{myname}}!!</p>
    </body>
</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.

<!doctype html>
<html>
<head>
  <meta charset="utf-8"/>
  <title>DashBoard</title>
  <link rel="stylesheet" href="webjars/bootstrap/3.2.0/css/bootstrap.css"/>
  <link rel="stylesheet" href="webjars/font-awesome/4.1.0/css/font-awesome.css"/>
  <link rel="stylesheet" href="css/styles.css"/>

</head>
<body ng-app>
        <p>Enter Name: <input type="text" ng-model="myname"> </p>
        <p>Hello {{myname}}!!</p>
	
	<script src="webjars/jquery/1.11.1/jquery.js"></script>
	<script src="webjars/bootstrap/3.2.0/js/bootstrap.js"></script>
	<script src="webjars/angularjs/1.2.19/angular.js"></script>
	<script src="webjars/angularjs/1.2.19/angular-route.js"></script>
	<script src="js/app.js"></script>
	<script src="js/controllers.js"></script>
	<script src="js/services.js"></script>

</body>
</html>

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

package com.sivalabs.app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

@Controller
class HomeController
{
    @RequestMapping("/")
    public String home() {
        return "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.

package com.sivalabs.app.entities;
@Entity
public class Todo {
	@Id @GeneratedValue(strategy=GenerationType.AUTO)
	private Integer id;
	private String description;
	@Temporal(TemporalType.TIMESTAMP)
	private Date createdOn = new Date();
	
	//setters and getters
}

package com.sivalabs.app.repos;
public interface TodoRepository extends JpaRepository<Todo, Integer>{
}

package com.sivalabs.app.controllers;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.sivalabs.app.entities.Todo;
import com.sivalabs.app.repos.TodoRepository;

@RestController
@RequestMapping("/todos")
public class TodoController {

    @Autowired
    private TodoRepository todoRepository;

    @RequestMapping(value="", method=RequestMethod.GET)
    public List<Todo> persons() {
        return todoRepository.findAll();
    }    
    @RequestMapping(value="", method=RequestMethod.POST)
    public Todo create(@RequestBody Todo todo) {
		return todoRepository.save(todo);
	}
    
    @RequestMapping(value="/{id}", method=RequestMethod.DELETE)
    public void delete(@PathVariable("id") Integer id) {
    	todoRepository.delete(id);
	}
}

Create DatabasePopulator to setup some initial data.

package com.sivalabs.app;

import java.util.Arrays;
import java.util.Date;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.sivalabs.app.entities.Todo;
import com.sivalabs.app.repos.TodoRepository;

@Component
public class DatabasePopulator 
{
	@Autowired
    private TodoRepository todoRepository;
	
	@PostConstruct
	void init()
	{
		try {			
			Todo t1 = new Todo(null, "Task 1", new Date());
			Todo t2 = new Todo(null, "Task 2", new Date());
			Todo t3 = new Todo(null, "Task 3", new Date());
			this.todoRepository.save(Arrays.asList(t1,t2,t3));
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

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.

var myApp = angular.module('myApp',['ngRoute']);

myApp.config(['$routeProvider','$locationProvider',
        function($routeProvider, $locationProvider) {
          $routeProvider
          	.when('/home', {
              templateUrl: 'templates/home.html',
              controller: 'TodoController'
          	})
            .otherwise({
            	redirectTo: 'home'
            });
          
}]);

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

<!doctype html>
<html ng-app="myApp">
<head>
  <meta charset="utf-8"/>
  <title>DashBoard</title>
  <link rel="stylesheet" href="webjars/bootstrap/3.2.0/css/bootstrap.css"/>
  <link rel="stylesheet" href="webjars/font-awesome/4.1.0/css/font-awesome.css"/>
  <link rel="stylesheet" href="css/styles.css"/>	

</head>
<body>
    
    <div class="container">    
          <div ng-view></div>
    </div>

	<script src="webjars/jquery/1.11.1/jquery.js"></script>
	<script src="webjars/bootstrap/3.2.0/js/bootstrap.js"></script>
	<script src="webjars/angularjs/1.2.19/angular.js"></script>
	<script src="webjars/angularjs/1.2.19/angular-route.js"></script>
	
	<script src="js/app.js"></script>
	<script src="js/controllers.js"></script>
	<script src="js/services.js"></script>
	
</body>
</html>

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

<div class="col-md-8 col-md-offset-2">

<form class="form-horizontal" role="form">
  	<div class="form-group form-group-md">
  		<div class="col-md-10">
			<input type="text" class="form-control" ng-model="newTodo.description"> 
		</div>
		<button class="btn btn-primary" ng-click="addTodo(newTodo)">Add</button>
	</div>
</form>


<table class="table table-striped table-bordered table-hover">
	<thead>
		<tr>
			<th width="70%">Item</th>
			<th>Date</th>
			<th>Delete</th>
		</tr>
	</thead>
	<tbody>
		<tr ng-repeat="todo in todos">
			<td>{{todo.description}}</td>
			<td>{{todo.createdOn | date}}</td>
			<td><button class="btn btn-danger" ng-click="deleteTodo(todo)">Delete</button></td>
		</tr>
	</tbody>
</table>
<br/>
</div>

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.

angular.module('myApp')
.controller('TodoController', [ '$scope', '$http', function ($scope, $http) {
	
	$scope.newTodo = {};
	
	$scope.loadTodos = function(){
		$http.get('todos')
		.success(function(data, status, headers, config) {
			$scope.todos = data;
		 })
		.error(function(data, status, headers, config) {
		      alert('Error loading Todos');
		});
	};
	
	$scope.addTodo = function(){
		$http.post('todos',$scope.newTodo)
		.success(function(data, status, headers, config) {
			$scope.newTodo = {};
			$scope.loadTodos();
		 })
		.error(function(data, status, headers, config) {
		      alert('Error saving Todo');
		});
	};
	
	$scope.deleteTodo = function(todo){
		$http.delete('todos/'+todo.id)
		.success(function(data, status, headers, config) {
			$scope.loadTodos();
		 })
		.error(function(data, status, headers, config) {
		      alert('Error deleting Todo');
		});
	};
	
	$scope.loadTodos();
}]);

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!

Siva Reddy

Katamreddy Siva Prasad is a Senior Software Engineer working in E-Commerce domain. His areas of interest include Object Oriented Design, SOLID Design principles, RESTful WebServices and OpenSource softwares including Spring, MyBatis and Jenkins.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

4 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
ukbarr
ukbarr
9 years ago

Thanks for the start up. It’s give a good idea of the simplicity of all that compared to my actual stack (JSF).

Waiting the next article.

Siva
9 years ago
Muralikrishna
Muralikrishna
8 years ago

Good start up and started looking at your second article.

Hercial Vitalis
7 years ago

I intend to look into this language.

Back to top button