LWC Ex 1: Simple Calculator

Create a Lightning web component in VS Code called calcFull – this will generate the html and js files. You can use the below code to try out the solution and customize it further if you need to.

Disclaimer – please note that this is just one way to address the requirement – there could be more and better ways to solve this. The code sample is only to give you an idea – feel free to try more innovative ways of solving this challenge.

calcFull.html

<template>
    <div class="slds-m-around_small" style="display: inline-block">
        <lightning-card title="Full Calculator" icon-name="custom:custom34">
            <div>
                <lightning-input
                value={calcExpression}
                label="Calc Expression"
                name="txtExpression"
                readonly>
                </lightning-input>
            </div>
            <div>
                <lightning-input
                value={showResult}
                label="Result"
                name="txtResult"
                readonly>
                </lightning-input>
            </div>
            <div style="display: inline-block">
                <table class="slds-table slds-table_cell-buffer slds-table_bordered">
                        <tr class="slds-line-height_reset">
                                <td>
                                    <div class="slds-truncate">
                                        <lightning-button
                                            variant="brand-outline"
                                            label="1"
                                            onclick={handleClick}
                                        ></lightning-button>
                                    </div>
                                </td>
                                <td>
                                    <div class="slds-truncate">
                                        <lightning-button
                                            variant="brand-outline"
                                            label="2"
                                            onclick={handleClick}
                                        ></lightning-button>
                                    </div>
                                </td>
                                <td>
                                    <div class="slds-truncate">
                                        <lightning-button
                                            variant="brand-outline"
                                            label="3"
                                            onclick={handleClick}
                                        ></lightning-button>
                                    </div>
                                </td>
                                <td>
                                    <div class="slds-truncate">
                                        <lightning-button
                                            variant="brand"
                                            label="+"
                                            onclick={handleClick}
                                        ></lightning-button>
                                    </div>
                                </td>
                        </tr>
                        <tr class="slds-line-height_reset">
                            <td>
                                <div class="slds-truncate">
                                    <lightning-button
                                        variant="brand-outline"
                                        label="4"
                                        onclick={handleClick}
                                    ></lightning-button>
                                </div>
                            </td>
                            <td>
                                <div class="slds-truncate">
                                    <lightning-button
                                        variant="brand-outline"
                                        label="5"
                                        onclick={handleClick}
                                    ></lightning-button>
                                </div>
                            </td>
                            <td>
                                <div class="slds-truncate">
                                    <lightning-button
                                        variant="brand-outline"
                                        label="6"
                                        onclick={handleClick}
                                    ></lightning-button>
                                </div>
                            </td>
                            <td>
                                <div class="slds-truncate">
                                    <lightning-button
                                        variant="brand"
                                        label="-"
                                        onclick={handleClick}
                                    ></lightning-button>
                                </div>
                            </td>
                    </tr>
                    <tr class="slds-line-height_reset">
                        <td>
                            <div class="slds-truncate">
                                <lightning-button
                                    variant="brand-outline"
                                    label="7"
                                    onclick={handleClick}
                                ></lightning-button>
                            </div>
                        </td>
                        <td>
                            <div class="slds-truncate">
                                <lightning-button
                                    variant="brand-outline"
                                    label="8"
                                    onclick={handleClick}
                                ></lightning-button>
                            </div>
                        </td>
                        <td>
                            <div class="slds-truncate">
                                <lightning-button
                                    variant="brand-outline"
                                    label="9"
                                    onclick={handleClick}
                                ></lightning-button>
                            </div>
                        </td>
                        <td>
                            <div class="slds-truncate">
                                <lightning-button
                                    variant="brand"
                                    label="*"
                                    onclick={handleClick}
                                ></lightning-button>
                            </div>
                        </td>
                    </tr>
                    <tr class="slds-line-height_reset">
                        <td>
                            <div class="slds-truncate">
                                <lightning-button
                                    variant="destructive-text"
                                    label="CLR"
                                    onclick={handleClick}
                                ></lightning-button>
                            </div>
                        </td>
                        <td>
                            <div class="slds-truncate">
                                <lightning-button
                                    variant="brand-outline"
                                    label="0"
                                    onclick={handleClick}
                                ></lightning-button>
                            </div>
                        </td>
                        <td>
                            <div class="slds-truncate">
                                <lightning-button
                                    variant="success"
                                    label="="
                                    onclick={handleClick}
                                ></lightning-button>
                            </div>
                        </td>
                        <td>
                            <div class="slds-truncate">
                                <lightning-button
                                    variant="brand"
                                    label="/"
                                    onclick={handleClick}
                                ></lightning-button>
                            </div>
                        </td>
                    </tr>
                </table>
            </div>
        </lightning-card>
    </div>
</template>

calcFull.js

import { LightningElement } from 'lwc';

export default class CalcFull extends LightningElement {
    calcResult = '';
    calcExpression = '';
    clrExpression = false;
    prevOper = '';
    operations = {
        current: 0,
        '=': function(){
            return this.current;
        },
        '+': function(n){
            this.current += parseInt(n);
            return this;
        },
        '-': function(n){
            this.current -= parseInt(n);
            return this;
        },
        '*': function(n){
            this.current *= parseInt(n);
            return this;
        },
        '/': function(n){
            this.current /= parseInt(n);
            return this;
        }
    }

    get showResult(){
        return this.operations.current;
    }

    handleClick(event){
        if (this.clrExpression){
            this.calcExpression = '';
            this.calcResult = '';
            this.operations.current = 0;
            this.clrExpression = false;
        }
        this.calcExpression = this.calcExpression + event.target.label;
        if (event.target.label === "CLR"){
            this.calcResult = '';
            this.calcExpression = '';
            this.operations.current = 0;
        }
        else if (event.target.label === "+"){
            if (this.operations.current === 0)
            {
                this.operations.current = parseInt(this.calcResult);
            }
            else{
                this.calcResult = this.operations[this.prevOper](this.calcResult);
            }
            this.prevOper = '+';
            this.calcResult = '';
        }
        else if (event.target.label === "-"){
            if (this.operations.current === 0)
            {
                this.operations.current = parseInt(this.calcResult);
            }
            else{
                this.calcResult = this.operations[this.prevOper](this.calcResult);
            }
            this.prevOper = '-';
            this.calcResult = '';
        }
        else if (event.target.label === "*"){
            if (this.operations.current === 0)
            {
                this.operations.current = parseInt(this.calcResult);
            }
            else{
                this.calcResult = this.operations[this.prevOper](this.calcResult);
            }
            this.prevOper = '*';
            this.calcResult = '';
        }
        else if (event.target.label === "/"){
            if (this.operations.current === 0)
            {
                this.operations.current = parseInt(this.calcResult);
            }
            else{
                this.calcResult = this.operations[this.prevOper](this.calcResult);
            }
            this.prevOper = '/';
            this.calcResult = '';
        }
        else if (event.target.label === "="){
            this.calcResult = this.operations[this.prevOper](this.calcResult);
            this.calcResult = this.operations['=']();
            this.clrExpression = true;
        }
        else{
            this.calcResult = this.calcResult + event.target.label;
            
        }
    }
}

You can view the component in action using your local Dev Server if you have set it up. Use the below links to set up Local Dev Server if you haven’t already done so:

Sample test cases:

  1. Type in 15+20 -5 * 60 / 9 – the Calc Expression should show the entire input string. The Result should should the output as the operations progress (35, 30, 1800 and finally 200). Please note we are not using BODMAS rule – instead evaluating from left to right in the above code. Hence the output that you get from the code will be different from that of an actual calculator.

2. Clicking on CLR or another digit (after = has published result) should reset the expression and the Result for the next new operation

3. Clicking on an operator in an invalid sequence will show a NaN error