Accomplishing Tasks Using AngularJS Services

Alec Wassill
4 min readFeb 29, 2016

--

Using AngularJS Services to create modular, responsible, testable, business logic level code is great! In this post I’ll show you how to set up your web application to perform simple tasks and in doing so, write cleaner, reusable, inject-able code.

DISCLAIMER: We’ll be using a website that has view-routing set up already. The code that we’ll be starting with can be found here. To set up your website to be a Single Page Application, follow my steps in another post, here.

So, what is a service?

Services are meant to reuse business logic, and they help adhere to one of the main principles of Object Oriented Design, the Single Responsibility Principle, which states that an object should only have a single responsibility.

Services are great, because they do the work! They can be imported into other classes when you need them. This allows access to functionality exactly when you need it. Services are modular and are easily testable.

So to reiterate, services are reusable, they help adhere to the Single Responsibility Principle, and help with testability.

Let’s Get Started

First, we’re going to identify a need to create our first service. For the sake of simplicity and brevity, we’ll create a service to add, subtract, and concatenate numbers. Let’s set up our Page 1 view for these functions:

<div>
<h2>This is page 1!</h2>
<hr />
<h3>Simple Service Demonstration</h3>
<h3>Result: </h3>
</div>

Then we’ll need to add our form, which will hold our input boxes, and our buttons which will use our service:

<div>
<h2>This is page 1!</h2>
<hr />
<h3>Simple Service Demonstration</h3>
<form>
<label for="value1">First Value:</label>
<input type="text" name="value1" id="value1" placeholder="First Value" /><br />
<label for="value2">Second Value:</label>
<input type="text" name="value2" id="value2" placeholder="Second Value" /><br />
<input type="button" value="Add" />
<input type="button" value="Subtract" />
<input type="button" value="Concatenate" />
</form>
<h3>Result: </h3>
</div>

At the moment, these buttons don’t do anything. We could add code to a controller, and have it do the work, but that wouldn’t adhere to the Single Responsibility Principle we discussed earlier, so we’re going to put this code into our separate service.

Proper Separation

Before we do that though, we do need to create our controller to handle the values we enter, and the button clicks themselves! Remember, our code should do one thing well, and one thing only. This embodies the SRP.

Our code for Page1Controller.js:

angular.module('app').controller('Page1Controller', function($scope) {
//variables for our input boxes and the result
$scope.value1 = 0;
$scope.value2 = 0;
$scope.result = "";

//functions for our buttons to respond to our clicks
$scope.add = function() {
};

$scope.subtract = function() {
};

$scope.concat = function() {
};
});

We’ll include Page1Controller.js in our index.hmtl.

<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
<meta charset="UTF-8">
<title>Simple Service Demo</title>
</head>
<body>

<ul>
<li><a href="#/Dashboard">Home</a></li>
<li><a href="#/Page1">Page 1</a></li>
<li><a href="#/Page2">Page 2</a></li>
</ul>

<div ng-view></div>

<script src="https://code.angularjs.org/1.4.8/angular.min.js"></script>
<script src="https://code.angularjs.org/1.4.8/angular-route.min.js"></script>

<script src="App.js"></script>
<script src="RouteProvider.js"></script>

<script src="Page1Controller.js"></script>
</body>
</html>

As well as tell Angular to use our controller when we’re in our Page 1 view, using our RouteProvider.js:

angular.module('app').config(function ($routeProvider){

$routeProvider.
when('/Dashboard', {
templateUrl: "dashboard.html"
}).
when('/Page1', {
templateUrl: "page1.html",
controller: "Page1Controller"//add this line
}).
when('/Page2', {
templateUrl: "page2.html"
}).
otherwise({
redirectTo: '/Dashboard'
});
});

Then in page1.html, we’ll hook up our input boxes, buttons and output to our controller!

<div>
<h2>This is page 1!</h2>
<hr />
<h3>Simple Service Demonstration</h3>
<form>
<label for="value1">First Value:</label>
<input type="text" name="value1" id="value1" placeholder="First Value" ng-model="value1" /><br />
<label for="value2">Second Value:</label>
<input type="text" name="value2" id="value2" placeholder="Second Value" ng-model="value2" /><br />
<input type="button" value="Add" ng-click="add()" />
<input type="button" value="Subtract" ng-click="subtract()" />
<input type="button" value="Concatenate" ng-click="concat()" />
</form>
<h3>Result: {{result}}</h3>
</div>

Ng-model links our values in the input boxes to the values in our controller through data binding, which I’ll cover in my next blog post!

Ng-click tells Angular to run a function in our controller whenever this button is clicked.

The {{result}} will automatically update on our page when the value of our result in the controller changes, which we’ll change using our service.

Finally, Our Simple Service

The code for our SimpleService.js:

angular.module('app').service('SimpleService', function() {

return({
add: add,
subtract: subtract,
concat: concat
});

function add(value1, value2) {
return parseInt(value1) + parseInt(value2);
}

function subtract(value1, value2) {
return parseInt(value1) - parseInt(value2);
}

function concat(value1, value2) {
return value1 + value2;
}
});

This will perform our work for us, as simple as it is, but the theory is the same for the majority of services.

Let’s go ahead and inject our SimpleService into our Page1Controller, and add the code to tell our service to do accomplish a task.

angular.module('app').controller('Page1Controller', function($scope, SimpleService) { //note the injection up here

//variables for our input boxes and the result
$scope.value1 = 0;
$scope.value2 = 0;
$scope.result = "";

//functions for our buttons to respond to our clicks
$scope.add = function() {
$scope.result = SimpleService.add($scope.value1, $scope.value2);
};

$scope.subtract = function() {
$scope.result = SimpleService.subtract($scope.value1, $scope.value2);
};

$scope.concat = function() {
$scope.result = SimpleService.concat($scope.value1, $scope.value2);
};
});

Then we’ll include our SimpleService.js into our index.html.

<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
<meta charset="UTF-8">
<title>Simple Service Demo</title>
</head>
<body>

<ul>
<li><a href="#/Dashboard">Home</a></li>
<li><a href="#/Page1">Page 1</a></li>
<li><a href="#/Page2">Page 2</a></li>
</ul>

<div ng-view></div>

<script src="https://code.angularjs.org/1.4.8/angular.min.js"></script>
<script src="https://code.angularjs.org/1.4.8/angular-route.min.js"></script>

<script src="App.js"></script>
<script src="RouteProvider.js"></script>

<script src="Page1Controller.js"></script>

<script src="SimpleService.js"></script>
</body>
</html>

We’re Done!

We now have our application doing work for us, and in an Object Oriented, responsible manner!

Play around with it, and try thinking of more complex uses we could use our services for.

Until next time!

-Alec Wassill

--

--