AngularJS- Simple Calculator
Today I wanted to explain you how to make AngularJS- Simple Calculator. Recently, my attention was drawn to an interesting JavaScript framework called AngularJS. It is a framework created by Google to facilitate the creation of rich applications for web browsers. In this article I would like to present an example of an application created using AngularJS, which will use several important functionalities provided by this framework. Of course, I’m just beginning to learn about AngularJS, so in this article I will limit myself to the most basic AngularJS features. 1. Application concept Our application will be a very simple mathematical calculator that will enable the user to perform four basic operations: adding, subtracting, multiplying and dividing into integers. We expect more or less the appearance of this calculator.
2. AngularJS Library AngularJS is distributed as a single JavaScript file, which is available at angularjs.org. All you have to do is select the stable version and minimized the file. This version of the file is called angular.min.js. At the time of writing this article, the latest stable version was 1.0.7. 3. Application structure Our application will be placed in the following directory structure:
1
2
3
4
5
6
7
|
Calculator Main file |--lib | |--js JavaScript library |--app |--js Source files JavaScript |--style CSS files |--view HTML files |
After creating the above directory structure, copy the downloaded angular.min.js file to the Calculator / lib / js directory. Then create the basic source files in which we will define our application. We will need three files:
- Calculator/index.html – basic view layer file
- Calculator/app/js/app.js – basic file with application sources
- Calculator/app/style/default.css – file containing cascading styles
4. AngularJS application In the next step, we will create the HTML framework of our application, in which we define the basic HTML elements and include our source files. The resulting index.html file should look like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> < html ng-app = "calculatorApplication" > < head > < meta http-equiv = "Content-Type" content = "text/html; charset=utf-8" > < script src = "lib/js/angular.min.js" type = "text/javascript" ></ script > < script src = "app/js/app.js" type = "text/javascript" ></ script > < link href = "app/style/default.css" rel = "stylesheet" type = "text/css" > </ head > < body > < div ng-view></ div > </ body > </ html > |
In addition to the standard html header, there are two elements specific to the AngularJS application:
- <html ng-app=”calculatorApplication”>
The ng-app parameter tells the AngularJS engine that everything inside the html tag is an application controlled by AngularJS. And that it is a module called calculatorApplication.
<div ng-view> </ div>
The ng-view parameter indicates that this element will be a container in which AngularJS will place the created view.
As you can see, the framework extends the HTML standard with its own attributes, which can be interpreted by the AngularJS engine.
After creating the HTML structure of the application, we should define the behavior of the application. We will do this by editing the app.js file and adding the following code:
?
1
var app = angular.module (“calculatorApplication”, []);
This construction will create an AngularJS module called calculatorApplication. Empty square brackets mean an empty list of dependencies required by our application.
In the next step, we want to define the basic behavior. We would like our application to have a start page containing a welcome message and a link to the calculator.
This page should look like this (in free translation: This is the start page. You can go to the calculator):
As you can see the url of the page has an interesting ending # / home. It is simply the address of the subpage in our application. This is the standard way in which pages in AngularJS are defined. Then we would like to associate the address / home with some content. To do this, add the controller definition for this page by changing the app.js file as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
var app = angular.module( "calculatorApplication" , []).config( function ($routeProvider) { $routeProvider.when( "/home" , { templateUrl: "app/view/home.html" , controller: "HomeController" }); $routeProvider.otherwise({ redirectTo: "/home" }); }); app.controller( "HomeController" , function () { }); |
There are several interesting things happening in this part of the code. First, we call the config method and pass it as a parameter to the function that configures our application. This function accepts the $ routeProvider parameter, which is responsible for associating url addresses (including suffix / home) with appropriate behavior. In our case, we want to use the home.html template as the view pattern and the HomeController controller when the address / suffix is in the address. In any other case, we want the browser to be redirected to this address. In addition, we have defined a controller called HomeController, which does not support any specific functionality. The last thing we need to do is define a template for our homepage. To do this, create the Calculator / app / view / home.html file and place the following content in it:
1
2
3
4
5
6
7
8
|
< div > < div > This is home page: </ div > < div > You can go to < a href = "#/calculator" >Calculator</ a >. </ div > </ div > |
As you can see, this is a very simple html code that will display a welcome message and a link to the page with the calculator (which we have not yet created). 5. The first attempt to run the application Let’s try now to check if our application works. You can do it in two ways: Put it in the http server and open the address of the index.html file in the browser Open the index.html file straight from the file system For now, let’s use the latter option;) Warning! Due to security policies, some Internet browsers may block access to local files for AJAX calls from javascript. This case occurs at least in Google Chrome and Internet Explorer browsers. I do not know how to solve this in the case of IE, but if you want to test the application from Chroma, you must run the browser with the –allow-file-access-from-files parameter as described in the question on stackoverflow. This solution is not necessary if you are accessing the application through an http server. In the case of Mozilla Firefox, our application should work properly without any additional changes. 6. Calculator page To add a calculator to our application, we must create a html template that will define the appearance of our calculator. We will put it in the file Calculator / app / view / calculator.html:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
< div class = "calculator" > < div class = "display" >0</ div > < div class = "digitsKeyboard" > < div class = "digitKey" >1</ div > < div class = "digitKey" >2</ div > < div class = "digitKey" >3</ div > < div class = "digitKey" >4</ div > < div class = "digitKey" >5</ div > < div class = "digitKey" >6</ div > < div class = "digitKey" >7</ div > < div class = "digitKey" >8</ div > < div class = "digitKey" >9</ div > < div class = "digitKey" >0</ div > < div class = "equalSignKey" >=</ div > </ div > < div class = "operationsKeyboard" > < div class = "operationKey" >/</ div > < div class = "operationKey" >*</ div > < div class = "operationKey" >+</ div > < div class = "operationKey" >-</ div > </ div > </ div > |
The calculator consists of a display display, a keyboard with digits and the digitsKeyboard equality sign and a keyboard with operationKeyboard mathematical operation keys. In addition, we need to define a CSS style that will describe the detailed appearance of our calculator. To do this, place the following CSS code in the Calculator / app / style / default.css file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
.calculator { display : inline- block ; background-color : black ; height : 240px ; width : 208px ; overflow : hidden ; } .display { background-color : #DDDDDD ; border : 1px solid black ; font-family : monospace ; font-size : 27px ; font-weight : bold ; height : 30px ; padding : 0 4px ; text-align : right ; width : 198px ; overflow : hidden ; } .digitsKeyboard { overflow : hidden ; width : 156px ; float : left ; } .digitKey { width : 50px ; height : 50px ; background-color : #AABBCC ; } .equalSignKey { width : 102px ; height : 50px ; background-color : #AACCBB ; } .operationsKeyboard { overflow : hidden ; width : 52px ; height : 208px ; float : left ; } .operationKey { width : 50px ; height : 50px ; background-color : #CCAABB ; } .digitKey, .equalSignKey, .operationKey { cursor : pointer ; font-family : monospace ; font-size : 33px ; border : 1px solid black ; line-height : 50px ; text-align : center ; float : left ; } .digitKey:hover, .equalSignKey:hover, .operationKey:hover { opacity: 0.8 ; } .digitKey:active, .equalSignKey:active, .operationKey:active { opacity: 0.7 ; } |
The last thing to do is map the address / calculator in the application. To do this, we need to add the calculator page to $ routeProvider in the same way we defined the main page. So add the following code to the Calculator / app / js / app.js file:
1
2
3
4
|
$routeProvider.when( "/calculator" , { templateUrl: "app/view/calculator.html" , controller: "CalculatorController" }); |
And define a new, empty (for now) calculator controller:
1
2
|
app.controller( "CalculatorController" , function () { }); |
You can now try to open the calculator in your browser. Just open the index.html file and click the calculator link. Then you should see the calculator on the screen. 7. Definition of fixed values We will now add some life to the CalculatorController. To do this, let’s start with changing the function provided in the controller’s declaration:
1
2
|
app.controller( "CalculatorController" , function ($scope) { }); |
As you can see, we added the $ scope parameter to the function definition. It is an object in which the state of our application is stored. For our needs just know that we can define any field in it that will be available in other places of the application.
Let’s begin by defining the list of calculator keys, along with the parameters by placing this code in the controller function:
Number keys
1
2
3
4
5
6
|
$scope.digitKeys = [ {label: "1" , value: 1}, {label: "2" , value: 2}, {label: "3" , value: 3}, {label: "4" , value: 4}, {label: "5" , value: 5}, {label: "6" , value: 6}, {label: "7" , value: 7}, {label: "8" , value: 8}, {label: "9" , value: 9}, {label: "0" , value: 0} ]; |
We used the digitKeys field to define an array of objects representing each digit on the calculator keyboard. Each key has a label label that will be displayed on the key and a value that will be used for calculations. The equality key
1
|
$scope.equalSignKey = {label: "=" }; |
Here we have defined the equality key, which only requires labeling. This definition was created only to maintain consistency in the way keys are defined. Another solution would be to put the = sign directly in the html file.
Operation keys
1
2
3
4
5
6
|
$scope.operationKeys = [ {label: "/" , operation: function (a, b) { return a / b}}, {label: "*" , operation: function (a, b) { return a * b}}, {label: "+" , operation: function (a, b) { return a + b}}, {label: "-" , operation: function (a, b) { return a - b}} ]; |
The last set of keys represents mathematical operations. As you can see, we placed a function in each object, thanks to which we will be able to easily perform the desired operation. 8. Dynamic generation of calculator keys After defining the keys in the CalculatorController, we can use them to simplify our html template by dynamically generating keys. Let’s start with the simplest case, i.e. the equality button:
1
2
3
|
< div class = "equalSignKey" > {{ equalSignKey.label }} </ div > |
In this case, we used the structure {{}} to tell AngularJS that we want to place the equalSignKey.label value here. Angular will search this value in the $ scope object and associate it with the appropriate part of the html file. We will do the same for the number keys, but for that we will use a directive called ng-repeat, which allows you to iterate through the element table and create an html tag for each of them:
1
2
3
|
< div class = "digitKey" ng-repeat = "key in digitKeys" > {{ key.label }} </ div > |
In this case, AngularJS iterates over the elements from the $ scope.digitKeys array and assigns subsequent elements to the key variable. Thanks to this, we do not have to repeat the html code for each key. We will do the same for the operation keys:
1
2
3
|
< div class = "operationKey" ng-repeat = "key in operationKeys" > {{ key.label }} </ div > |
So the resulting calculator.html file should look like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
< div class = "calculator" > < div class = "display" >0</ div > < div class = "keyboard" > < div class = "digitKey" ng-repeat = "key in digitKeys" > {{ key.label }} </ div > < div class = "equalSignKey" ng-click = "compute()" > {{ equalSignKey.label }} </ div > </ div > < div class = "operations" > < div class = "operationKey" ng-repeat = "key in operationKeys" > {{ key.label }} </ div > </ div > </ div > |
At this point, you can test again whether our calculator is displayed correctly.
9. Operation of the calculator
Now we want our calculator to work as real, so we need to define variables that will store the current state of the calculator. We need five such variables:
displayValue – the current value displayed on the screen of the calculator
valueA – the first (left) value used for calculations
valueB – the second (right) value used for calculations
selectedOperation – which mathematical operation was selected by the user
clearValue – should pressing the next digit clear the screen?
Let’s define them in the $ scope object and initialize them with default values. Let’s add this code inside the CalculatorController:
1
2
3
4
5
|
$scope.displayValue = 0; $scope.valueA = 0; $scope.valueB = 0; $scope.selectedOperation = null ; $scope.clearValue = true ; |
10. Binding the variable displayValue to the displayed value Once we have the variable displayValue, we would like it to be displayed on the screen of our calculator. And this is where the best AngularJS feature comes into play. Just put the {{displayValue}} tag inside calculator.html changing <div class = “display”> 0 </ div> to make it look like this:
1
|
< div class = "display" >{{ displayValue }}</ div > |
That’s all!
From that moment, AngularJS will do its tricks, ensuring that the displayed value will be equal to the variable value. If you change the value assigned to the variable, the value displayed on the calculator screen will change automatically.
That’s not all, if we allowed the user to directly edit the screen, AngularJS would automatically change the value of the variable. So this connection works both ways, which greatly simplifies writing our application.
11. Save the calculator buttons
We already have all the calculator elements in place, so it’s time to get a little bit of life in it. The main idea is to associate buttons with appropriate behavior. To do this, we will use the ng-click directive. Let’s change the calculator.html template:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
< div class = "calculator" > < div class = "display" >{{ displayValue }}</ div > < div class = "digitsKeyboard" > < div class = "digitKey" ng-repeat = "key in digitKeys" ng-click = "digitClicked(key.value)" > {{ key.label }} </ div > < div class = "equalSignKey" ng-click = "compute()" > {{ equalSignKey.label }} </ div > </ div > < div class = "operationsKeyboard" > < div class = "operationKey" ng-repeat = "key in operationKeys" ng-click = "operationClicked(key.operation)" > {{ key.label }} </ div > </ div > </ div > |
In this part of the code, we added three three ng-click directives that contain simple JavaScript function calls: For keys with numbers: ng-click = “digitClicked (key.value)” For operation keys: ng-click = “operationClicked (key.operation)” For the equal sign: ng-click = “compute ()” As you can see, we could pass the data previously defined in AngularJS variables in the same way that we passed them earlier in blocks {{}}. We want the pressing of a particular button to trigger the corresponding function assigned to it. Let’s now define these three functions inside the CalculatorController. Importantly, these functions will be defined as part of the $ scope object: Function for handling numbers buttons:
1
2
3
4
5
6
7
8
9
|
$scope.digitClicked = function (digit) { if ($scope.clearValue) { $scope.displayValue = digit; $scope.clearValue = false ; } else { $scope.displayValue = $scope.displayValue * 10 + digit; } $scope.valueB = $scope.displayValue }; |
After clicking the number button, we want to update the value displayed on the screen by replacing the currently displayed number, or by increasing the displayed number by the next digit (just multiply the displayed number by 10 and add the selected number to the result). In addition, we must remember the displayed number as the second value that we put in to perform a mathematical operation. Function for handling operation buttons:
1
2
3
4
5
6
|
$scope.operationClicked = function (operation) { $scope.selectedOperation = operation; $scope.valueA = $scope.displayValue; $scope.valueB = $scope.displayValue; $scope.clearValue = true ; }; |
In the case when the user clicks on the operation button, we just need to remember which operation selected and assign the displayed value to both variables that we will be able to use to perform this operation. In addition, we need to set the flag clearValue, so that the next click in the number will replace the number displayed on the screen. Function to handle the equality button:
1
2
3
4
5
6
7
8
|
$scope.compute = function () { if ($scope.selectedOperation != null ) { $scope.displayValue = Math.floor( $scope.selectedOperation($scope.valueA, $scope.valueB)); $scope.clearValue = true ; $scope.valueA = $scope.displayValue; } } |
The last function is responsible for calculating the result if the operation was previously selected (assigned to the field $ scope.selectedOperation). This is done by simply calling the memorized function. In addition, the clearValue flag is set and the result of the calculation is remembered as the first component of the next operation. Summary That’s all, we already have a fully functional calculator for web browsers. As you can see AngularJS is simple to use (at least when creating a calculator) and a very helpful framework for applications written in JavaScript. It gives us new possibilities of linking the application state with the view layer based on html, which greatly simplifies the creation of dynamic solutions. The full source code for this calculator is available below.
Hope you learned something new
If you learned something new from this tutorial or if you have any question let me know in comments section.