Build a Scientific Calculator with Vue.js

Raphael Ugwu
👁️ 10,593 views
💬 comments

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.

Table of Contents

    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:<event-type> directive in our HTML where <event-type> 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.

    Raphael Ugwu

    1 post

    Web Developer, Community Builder and a huge fan of Open Source