Build a Scientific Calculator with Vue.js

By Raphael Ugwu

Vue gives the everyday software developer a certain flexibility and seamless experience that may be hard to come across when using other frameworks to build applications.

Unlike other frameworks, Vue’s Model-View-View-Model (MVVM) architectural pattern makes it extremely easy and fun to work with.

In this article, we’re going to build a scientific calculator with Vue. When we are done, you should be able to perform routine tasks such as:

  • Handling user input
  • Rendering data to the DOM using template syntax
  • Become familiar with basic Vue directives used for handling data
  • Creating Vue instances

Below is a basic preview of the app we’ll be building:

Starting a New Project with Vue.js

If you’re using Vue for the first time, you should install the Vue CLI globally via npm:

# install globally
npm install -g vue-cli  

Another way of integrating Vue to your application is via its CLI:

# create a new project using the "webpack" template
vue init webpack my-project

# install dependencies
cd my-project
npm install

# Start the app
npm run dev

One other way of using Vue is by including it directly in the browser via a script tag:

<script> https://unpkg.com/vue </script>

This method is recommended for beginners and is particularly handy when we are building lightweight, front end applications for easier rendering and faster loading speed. This method is what we will be using in our examples:

<html>
  <head></head>
  <body>

    <!-- App View here -->

    <script src="https://unpkg.com/vue"></script>
    <script>
      // Vue app here
      var app = new Vue({/* Coming soon */})
    </script>
  </body>
</html>

Creating a Vue Instance for our App

Every Vue application starts by creating a new Vue instance which contains data and methods that control the behavior of our app. These data and methods can be updated and in turn our app view will also be updated to match their current values. The portion of the view that needs to be controlled by Vue is tracked with the el property:

// new Vue instance
var app = new Vue({
  // element property which points to the DOM
  el: "#app",
  data: {
    // the data we'll use in 
    // building our app goes in here
  },
  methods : {
    // the functions we'll use in 
    // controlling our app go in here
  };
});    

The el property takes a CSS selector, therefore it must match an element on the DOM:

<div id="app>
  <!-- our entire HTML will be placed inside this div -->
</div>

Adding our calculator’s input screen

To start binding values to the view, all we have to do is add an input element in our HTML file and using the v-model directive, set it to receive and handle data using v-model. We’ll equate the value of v-model to our data object value current :

<div class="results">
  <input class="input" v-model="current">
</div>

The value we are binding to the view is stored in the data object as seen below:

var app = new Vue({
  el: "#app",
  data: {
    current: '',
  }
});

Adding our calculator buttons

Vue offers seamless event handling and state change triggers by allowing us create methods in our Vue instance. We can bind these methods to the v-on: directive in our HTML where can be click, mouse-over, etc. To make each calculator button functional, we’ll add the Vue directive v-on:click to it. In our Vue instance, we’ll create a method and name it press. Our button functionalities are controlled by press and it’s also responsible for input display behavior as well as button behavior. We’ll then map the value of v-on:click to press in our HTML, whenever a button is clicked, it then exhibits it’s intended action as expressed in the press method embedded in our Vue instance.

<button class="button" v-on:click="press">7</button>
<button class="button" v-on:click="press">8</button>
<button class="button" v-on:click="press">9</button>
<button class="button" v-on:click="press">4</button>
<button class="button" v-on:click="press">5</button>
<button class="button" v-on:click="press">6</button>
<button class="button" v-on:click="press">1</button>
<button class="button" v-on:click="press">2</button>
<button class="button" v-on:click="press">3</button>
<button class="button equal-sign" v-on:click="press">=</button>
<button class="button" v-on:click="press">C</button>
<button class="button" v-on:click="press">*</button>
<button class="button" v-on:click="press">/</button>
<button class="button" v-on:click="press">√</button>
<button class="button" v-on:click="press">x ²</button>

In the methods object, we define the press handler. Each time the method is called, it checks the value of the button and acts based on the value. For each button a different method (which we will create later) is executed. Some of these methods include divide(), multiply(), etc:

var app = new Vue({
  el: "#app",
  data: {
    current: '',
  },
  methods: {
    press: function(event) {
    //we make a reference to the inner text
    //of each button to dispatch our functions
     let key = event.target.innerText;
      if (
        key != '=' &&
        key != 'C' &&
        key != '*' &&
        key != '/' &&
        key != '√' &&
        key != 'x ²'
      ) {
        app.current += key;
      } else if (key === '=') {
        equals();
      } else if (key === 'C') {
        clear();
      } else if (key === '*') {
        multiply();
      } else if (key === '/') {
        divide();
      } else if (key === '√') {
        squareRoot();
      } else if (key === 'x ²') {
        square();
      }
    }
  }
});

Adding our calculation functions

We’ll add different functions to handle calculations and manage the state of calculations in our app. Calculations such as addition, subtraction, multiplication and division will be included in our functions. Advanced calculations will not be left out; mathematical concepts such as logarithms, sine, cosine and tangent will also be included as well.


 //our ' = ' button
function equals() {
  if ((app.current).indexOf("^") > -1) {
    var base = (app.current).slice(0, (app.current).indexOf("^"));
    var exponent = (app.current).slice((app.current).indexOf("^") + 1);
    app.current = eval("Math.pow(" + base + "," + exponent + ")");
  } else {
    app.current = eval(app.current)
  }
}

//our ' C ' button
function clear() {
  app.current = "";
}

//our ' <= ' button
function backspace() {
  app.current = app.current.substring(0, app.current.length - 1);
}

//our ' * ' button
function multiply() {
  app.current += "*";
}

//our ' / ' button
function divide() {
  app.current +=  "/";
}

//our ' + ' button
function plus() {
  app.current +=  "+";
}

//our ' - ' button
function minus() {
  app.current +=  "-";
}

//our ' sin ' button
function sin() {
  app.current = Math.sin(app.current);
}

//our ' cos ' button
function cos() {
  app.current = Math.cos(app.current);
}

//our ' tan ' button
function tan() {
  app.current = Math.tan(app.current);
}

//our ' log ' button
function log() {
  app.current = Math.log10(app.current);
}

Refer to the Pen on Codepen for all the methods. They are well explained with comments to guide you.

Toggling between Basic and Advanced Mode

Here we’ll proceed to give a full overview of how we’ll split the two modes of our calculator and have a button which when clicked can switch between both modes, depending on the nature of calculation we want to carry out.

  • First of all, in our Vue instance, a data property called changeMode is created and its initial value is set to true . We then proceed to our HTML where we give the parent element wrapping our calculator’s Basic Mode; which is the mode that ought to be seen first, the Vue directive v-show and then equate it to changeMode .
<div class="basic-mode" v-show="changeMode" >
  <!-- our calculator's basic functionalities are nested in here -->  
</div>   

Now update the data object to contain the changeMode property as well.

var app = new Vue({
  el: "#app",
  data: {
    current: '',
    changeMode: true
  },
});
  • Then we proceed to give the parent element wrapping our calculator’s Advanced Mode; the mode that we can change to, the Vue directive v-show . In this case, we equate v-show to !changeMode which is the exact opposite of changeMode .
<div class="advanced-mode" v-show="!changeMode" >
  <!-- our calculator's advanced functionalities are nested in here -->  
</div>   
  • Next, let’s add our toggle button. Nested in our button are two instructions: Show Advanced Mode and Show Basic Mode . Show Advanced Mode has a v-show directive that is set to changeMode , the idea being that if what we can see is the calculator’s Basic Mode, then the instruction our toggle button should be showing is Show Advanced Mode hence both of them having similar v-show properties. With this in mind, the v-show directive of Show Basic Mode is set to !changeMode .
<div id="app">
  <button class="changeMode">
    <!-- v-on:click directive to toggle between Basic and Advanced modes -->
    <p v-show="changeMode">Show Advanced Mode     ⚈</p>
    <p v-show="!changeMode">Show Basic Mode     ⚆</p>
    <!-- v-show directive to conditionally display both Basic and Advanced mode -->
  </button> 
</div>
  • We then give our toggle button a directive of v-on:click and equate it to changeMode = !changeMode. When the button is clicked, the view switches from changeMode to !changeMode and with it, every other element stored with the v-show directive of either changeMode or !changeMode .
<div id="app">
  <button class="changeMode" v-on:click="changeMode = !changeMode">
    <!-- v-on:click directive to toggle between Basic and Advanced modes -->
    <p v-show="changeMode">Show Advanced Mode     ⚈</p>
    <p v-show="!changeMode">Show Basic Mode     ⚆</p>
    <!-- v-show directive to conditionally display both Basic and Advanced mode -->
  </button> 
</div>

See the Pen Scientific Calculator with Vue.js by Raphael (@fullstackmafia) on CodePen.

Conclusion

It is now obvious that working with Vue could give you an edge. There are a handful of resources and articles that could get you started and on the right path, one of them is Christian Nwamba’s course on Vue, you can check it out here. Writing light and clean code that can be easily understood is commonplace among other things you can achieve with Vue.js. For a full view of the project, you can check it out on Github.

Source:: scotch.io