Angular Tutorial: Simple Calculator

Ashwin Sathian
7 min readApr 19, 2019

--

In this post, we’ll look at how we can build a simple calculator on Angular. You can see the live version of the application here. The GitHub repo for the app can be found here.

Project Setup

Assuming you have Angular CLI installed on your system(you can find instructions for this here), let’s start with creating the project. For this, open a Terminal(or Command Prompt if you’re on Windows), navigate to the directory where you want your project folder to be located and run the following command

ng new angularCalc

Now, the ‘angularCalc’ in that command is what I have named my project. This is purely your choice. Moving on, the next step is to install Bootstrap on your project. Always better to have Bootstrap on your project, rather than writing all the CSS yourself. You can find a quick guide on setting up Bootstrap styling in your project here. Since we are using Bootstrap, I have also made the application responsive.

We are done setting up. Let’s get creating !

The HTML

In this section, we are looking at the app.component.html file. Our calculator will be a very simple one, with the following features:

  • A Main Display, where the the keys we enter are recorded and the result is displayed
  • A Sub Display, which is a small section at the top of the main display where the calculation is displayed while the Main Display shows the error
  • An AC(All Clear) key which on press clears the displays
  • Four operator keys for + (Addition), — (Subtraction), x (Multiplication) and / (Division)
  • An ‘=’ key to perform the calculation
  • A ‘.’ key to enter decimal numbers

First, we have the displays, which we create as follows:

// Line 6 - Line 9
<div class="maindisplay">
<div class="subdisplay">{{ subText }}</div>
{{ mainText }}
</div>

Here, we have used string interpolation for setting text in the Main and Sub Displays, which will be set programatically through the mainText and subTextvariables.

What we need next is the keypad, which we build through the following code:

// Line 10 - Line 28
<div class="keypad">
<div class="keys ackey one-line" (click)="allClear()">AC</div>
<div class="keys opkey one-line" (click)="pressKey('/')">/</div>
<div class="keys numkey one-line" (click)="pressKey('7')">7</div>
<div class="keys numkey one-line" (click)="pressKey('8')">8</div>
<div class="keys numkey one-line" (click)="pressKey('9')">9</div>
<div class="keys opkey one-line" (click)="pressKey('x')">x</div>
<div class="keys numkey one-line" (click)="pressKey('4')">4</div>
<div class="keys numkey one-line" (click)="pressKey('5')">5</div>
<div class="keys numkey one-line" (click)="pressKey('6')">6</div>
<div class="keys opkey one-line" (click)="pressKey('-')">-</div>
<div class="keys numkey one-line" (click)="pressKey('1')">1</div>
<div class="keys numkey one-line" (click)="pressKey('2')">2</div>
<div class="keys numkey one-line" (click)="pressKey('3')">3</div>
<div class="keys opkey one-line" (click)="pressKey('+')">+</div>
<div class="keys numkey zerokey one-line" (click)="pressKey('0')">0</div>
<div class="keys numkey one-line" (click)="pressKey('.')">.</div>
<div class="keys equalkey one-line" (click)="getAnswer()">=</div>
</div>

As you can see, all keys have a common class keys, and then there are classes specific to each button or a set of then. We have also used Event Binding and assigned functions to be triggered on click of the buttons. What these functions do, adn what the classes are and do, we’ll see in the later sections.

Cool then. We now have a very ugly looking set of numbers and divs on our page. Don’t worry — they’ll get the perfect makeover soon enough.

The CSS

Let’s move on to app.component.css. Very well then, time to put some style on the calculator. We define styles for all those classes in the HTML.

Following are the main classes used in the HTML. These would get the calculator to look much better and closer to the final product.

// Line 8 - Line 43
.maindisplay {
background: lightgrey;
height: calc(100% / 3);
padding: 5% !important;
font-size: 4rem;
text-align: right;
font-family: Courier, monospace;
overflow: auto;
}
.subdisplay {
border-bottom: 1px solid black;
height: 25%;
font-size: 2rem;
overflow: auto;
}
.keypad {
height: calc(200% / 3);
}
.keys {
margin: 0;
width: 25%;
height: 20%;
background: whitesmoke;
color: black;
padding: 5%;
font-size: 2rem;
text-align: center;
cursor: pointer;
}
.one-line {
display: inline-block;
}

Of course, these are self explanatory as far as the CSS goes. Of course, we need a few more classes to give our calculator have the look we need — I leave that part to you. Use your imagination.

And finally, the business end — the Typescript

And here we are, ending it with the app.component.ts. This is where we do all the actual programming logic forthe calculator and just to cover most bases, I have used functions here, that go beyond the basic requirement of the calculator.

First, we have the following variables to declare and initialise — we’ll be using them soon.

// Line 10 - Line 17subText = ''; // The text that should appear in the sub-display
mainText = ''; // The text that should appear in the main display
operand1: number; // The first operand
operand2: number; // The second operand
operator = ''; // The operator
calculationString = '';
// This is the string that denotes the operation being performed
answered = false;
// A flag to check whether the solution has been processed
operatorSet = false; // You'll see how this is used soon

Once we have the variables ready, we can look at the function that handles press of each key on our calculator, pressKey

// Line 19 - Line 36pressKey(key: string) {
if (key === '/' || key === 'x' || key === '-' || key === '+') {
const lastKey = this.mainText[this.mainText.length - 1];
if (lastKey === '/' || lastKey === 'x' || lastKey === '-' || lastKey === '+') {
this.operatorSet = true;
}
if ((this.operatorSet) || (this.mainText === '')) {
return;
}
this.operand1 = parseFloat(this.mainText);
this.operator = key;
this.operatorSet = true;
}
if (this.mainText.length === 10) {
return;
}
this.mainText += key;
}

This function, which is triggered on pressing the number and operator keys, handles the input for the calculator. First, we check whether the pressed key is for an operator. Within this if block, we check whether the previously entered key was also an operator and if it were so, we just stop the execution, ensuring that two operators are not consecutively entered.

In the next if block, we ensure that the first key entry recorded isn’t an operator as that would make no sense. Once these checks pass, we set the current key as the operator, and all the input that preceded it as operand1. The operatorSet variable is used to check whether the operator has already been entered.

If it turns out that the pressed key is not an operator, we append the key entry to the mainText, so that it is displayed on the Main Display. We also have an if check to ensure only 10 characters are entered at most – as calculators have.

Next, we have the getAnswerfunction, that gets the calculator to well, calculate the answer.

// Line 44 - Line 78getAnswer() {
this.calculationString = this.mainText;
this.operand2 = parseFloat(this.mainText.split(this.operator)[1]);
if (this.operator === '/') {
this.subText = this.mainText;
this.mainText = (this.operand1 / this.operand2).toString();
this.subText = this.calculationString;
if (this.mainText.length > 9) {
this.mainText = this.mainText.substr(0, 9);
}
} else if (this.operator === 'x') {
this.subText = this.mainText;
this.mainText = (this.operand1 * this.operand2).toString();
this.subText = this.calculationString;
if (this.mainText.length > 9) {
this.mainText = 'ERROR';
this.subText = 'Range Exceeded';
}
} else if (this.operator === '-') {
this.subText = this.mainText;
this.mainText = (this.operand1 - this.operand2).toString();
this.subText = this.calculationString;
} else if (this.operator === '+') {
this.subText = this.mainText;
this.mainText = (this.operand1 + this.operand2).toString();
this.subText = this.calculationString;
if (this.mainText.length > 9) {
this.mainText = 'ERROR';
this.subText = 'Range Exceeded';
}
} else {
this.subText = 'ERROR: Invalid Operation';
}
this.answered = true;
}

The function here looks pretty long, but it isn’t all that complicated, as you’ll see.

Firstly, we set the mainText to the calculationString, and extract the second operand by splitting the calculationString by the operand, using the split() function, and assign it to operand2. What happens over the next few lines is pretty straightforward, carrying out the calculation and setting the answer to mainText, moving the calculation string to the subText. I have also included conditions to restrict the range of the calculations, and also display error messages.

Once this calculation is completed, we set the answered variable to true. We have use for this flag in other parts of the code, as you’ll see and figure out.

You’ll also need to write a function allClear() to be executed on pressing the AC key. And once that’s also done, we have a calculator that is good to go and ready to show off – to whoever may want to see it.

That rounds up this article where I explained how we can build a small calculator on Angular. Frankly, this app hardly uses any of the concepts that make Angular such a powerful and loved front-end development framework. Nevertheless, this application will help you familiarise yourself with the basic folder structure, project setup etc. and put you at ease with the combination of HTML, CSS and TS that make up an Angular component.

Do feel free to improve upon the features we already have and perhaps expand this to a scientific calculator, off the top of my head.

That’s all Folks!

Interested in having a 1:1 chat with me over this story, or Angular, Typescript and Javascript in general? Head over to Hire The Author and let’s connect!

--

--

Ashwin Sathian
Ashwin Sathian

Written by Ashwin Sathian

Full Stack Developer. Find me on Hire The Author, if you have queries about Angular, Node.js, MongoDB, the MEAN Stack or Web Development in general.

Responses (1)