Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

What causes the failure to update a template variable in this Vue calculator application?

I am working on a small calculator application with Vue 3. In the display section, I show both the results of the arithmetic operations and the "record" of the keys pressed:

<div class="display">
  <div class="track">
    {{track == '' ? ''  :  track + '=' }}
  </div>
  <div class="result">
    {{currentVal || 0}}
  </div>
</div>

I use a showOperationsTrack(clickedVal) method to display the afore mentioned "record":

const calculatorApp = {
  data() {
    return {
      track: "",
      currentVal: "",
      previousVal: null,
      operation: null,
      isOperatorClicked: false,
      isResultDisplayed: false
    };
  },
  methods: {
    showOperationsTrack(clickedVal) {
      if (!this.isResultDisplayed) {
        this.track = `${this.track}${clickedVal}`;
      } else {
        this.currentVal = "";
      }
    },
    appendClicked(clickedVal) {
      if (this.isOperatorClicked) {
        this.currentVal = "";
        this.isOperatorClicked = false;
      }

      if (this.isResultDisplayed) {
        this.currentVal = "";
        this.isResultDisplayed = false;
      }

      this.currentVal = `${this.currentVal}${clickedVal}`;

      this.showOperationsTrack(clickedVal);
    },
    appendDot() {
      if (this.currentVal.indexOf(".") === -1) {
        this.appendClicked(".");
      }
    },
    setPreviousVal() {
      this.previousVal = this.currentVal;
      this.isOperatorClicked = true;
    },
    add(clickedVal) {
      this.operation = (a, b) => a + b;
      this.setPreviousVal();
      this.showOperationsTrack(clickedVal);
    },
    subtract(clickedVal) {
      this.operation = (a, b) => a - b;
      this.setPreviousVal();
      this.showOperationsTrack(clickedVal);
    },
    multiply(clickedVal) {
      this.operation = (a, b) => a * b;
      this.setPreviousVal();
      this.showOperationsTrack(clickedVal);
    },
    divide(clickedVal) {
      this.operation = (a, b) => a / b;
      this.setPreviousVal();
      this.showOperationsTrack(clickedVal);
    },
    equals() {
      this.currentVal = this.operation(
        parseFloat(this.previousVal),
        parseFloat(this.currentVal)
      );
      this.isResultDisplayed = true;
      this.previousVal = null;
    },
    clearDisplay() {
      this.currentVal = "";
      this.track = "";
    }
  }
};
Vue.createApp(calculatorApp).mount("#myCalculator");
body {
  padding: 0;
  margin: 0;
}

body * {
  box-sizing: border-box;
}

.container {
  min-height: 100vh;
}

.calculator {
  font-family: Montserrat, sans-serif;
  width: 100%;
  max-width: 360px;
  min-width: 300px;
  margin: 10px auto;
  padding: 36px;
  background: #efefef;
  border-radius: 10px;
}

.display {
  position: relative;
  font-weight: bold;
  display: flex;
  flex-direction: column;
  background: #c3c3c3;
  border-radius: 10px;
  margin-bottom: 34px;
  padding: 10px 20px;
}

.result,
.track {
  display: flex;
  justify-content: flex-end;
}

.result {
  margin-top: 3px;
  font-size: 48px;
}

.track {
  position: absolute;
  top: 5px;
  left: 20px;
  right: 20px;
  font-size: 12px;
}

.buttons-container ol {
  list-style-type: none;
  padding: 0;
  margin: 0;
  color: #242424;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  column-gap: 10px;
  row-gap: 10px;
}

.buttons-container li,
.buttons-container .clear {
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 36px;
  height: 60px;
  font-weight: 600;
  background: #e7e7e7;
  border-radius: 7px;
  border: 1px solid rgba(0, 0, 0, 0.1);
  cursor: pointer;
}

.buttons-container li {
  width: 60px;
}

.buttons-container .clear {
  margin-top: 10px;
  text-transform: uppercase;
  font-weight: 600;
}

.buttons-container .orange {
  background: #ff9800;
  color: #fff;
}

.buttons-container .active {
  transform: translate(1px, -1px);
}
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500,600&display=swap" rel="stylesheet">
<script src="https://unpkg.com/vue@next"></script>

<div class="container">
  <div class="calculator" id="myCalculator">
    <div class="display">
      <div class="track">
        {{track == '' ? ''  :  track + '=' }}
      </div>
      <div class="result">
        {{currentVal || 0}}
      </div>
    </div>
    <div class="buttons-container">
      <ol>
        <li @click="appendClicked('7')">7</li>
        <li @click="appendClicked('8')">8</li>
        <li @click="appendClicked('9')">9</li>
        <li @click="divide('&divide;')">&divide;</li>
        <li @click="appendClicked('4')">4</li>
        <li @click="appendClicked('5')">5</li>
        <li @click="appendClicked('6')">6</li>
        <li @click="multiply('&times;')">&times;</li>
        <li @click="appendClicked('1')">1</li>
        <li @click="appendClicked('2')">2</li>
        <li @click="appendClicked('3')">3</li>
        <li @click="subtract('-')">-</li>
        <li @click="appendClicked('0')">0</li>
        <li @click="appendDot('.')">&middot;</li>
        <li @click="add('+')">+</li>
        <li @click="equals" class="orange">=</li>
      </ol>
      <div @click="clearDisplay" class="clear orange">Clear</div>
    </div>
  </div>
</div>

The problem

For a reason I’ve failed to spot, although the result is correctly set to 0 at the beginning of every new calculation, the operations record is not set to ''.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Questiones

  1. What causes this issue?
  2. What would be a reliable solution to it?

>Solution :

You can clear data property track when equal is pressed

const calculatorApp = {
  data() {
    return {
      track: "",
      currentVal: "",
      previousVal: null,
      operation: null,
      isOperatorClicked: false,
      isResultDisplayed: false,
    };
  },
  methods: {
    showOperationsTrack(clickedVal) {
      if (!this.isResultDisplayed) {
        this.track = `${this.track}${clickedVal}`;
      } else {
        this.currentVal = "";
      }
    },
    appendClicked(clickedVal) {
      if (this.isOperatorClicked) {
        this.currentVal = "";
        this.isOperatorClicked = false;
      }

      if (this.isResultDisplayed) {
        this.currentVal = "";
        this.isResultDisplayed = false;
      }

      this.currentVal = `${this.currentVal}${clickedVal}`;

      this.showOperationsTrack(clickedVal);
    },
    appendDot() {
      if (this.currentVal.indexOf(".") === -1) {
        this.appendClicked(".");
      }
    },
    setPreviousVal() {
      this.previousVal = this.currentVal;
      this.isOperatorClicked = true;
    },
    add(clickedVal) {
      this.operation = (a, b) => a + b;
      this.setPreviousVal();
      this.showOperationsTrack(clickedVal);
    },
    subtract(clickedVal) {
      this.operation = (a, b) => a - b;
      this.setPreviousVal();
      this.showOperationsTrack(clickedVal);
    },
    multiply(clickedVal) {
      this.operation = (a, b) => a * b;
      this.setPreviousVal();
      this.showOperationsTrack(clickedVal);
    },
    divide(clickedVal) {
      this.operation = (a, b) => a / b;
      this.setPreviousVal();
      this.showOperationsTrack(clickedVal);
      this.busy = true
    },
    equals() {
      this.currentVal = this.operation(
        parseFloat(this.previousVal),
        parseFloat(this.currentVal)
      );
      this.isResultDisplayed = true;
      this.previousVal = null;
      this.track = ''
    },
    clearDisplay() {
      this.currentVal = "";
      this.track = "";
    }
  }
};
Vue.createApp(calculatorApp).mount("#myCalculator");
body {
  padding: 0;
  margin: 0;
}

body * {
  box-sizing: border-box;
}

.container {
  min-height: 100vh;
}

.calculator {
  font-family: Montserrat, sans-serif;
  width: 100%;
  max-width: 360px;
  min-width: 300px;
  margin: 10px auto;
  padding: 36px;
  background: #efefef;
  border-radius: 10px;
}

.display {
  position: relative;
  font-weight: bold;
  display: flex;
  flex-direction: column;
  background: #c3c3c3;
  border-radius: 10px;
  margin-bottom: 34px;
  padding: 10px 20px;
}

.result,
.track {
  display: flex;
  justify-content: flex-end;
}

.result {
  margin-top: 3px;
  font-size: 48px;
}

.track {
  position: absolute;
  top: 5px;
  left: 20px;
  right: 20px;
  font-size: 12px;
}

.buttons-container ol {
  list-style-type: none;
  padding: 0;
  margin: 0;
  color: #242424;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  column-gap: 10px;
  row-gap: 10px;
}

.buttons-container li,
.buttons-container .clear {
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 36px;
  height: 60px;
  font-weight: 600;
  background: #e7e7e7;
  border-radius: 7px;
  border: 1px solid rgba(0, 0, 0, 0.1);
  cursor: pointer;
}

.buttons-container li {
  width: 60px;
}

.buttons-container .clear {
  margin-top: 10px;
  text-transform: uppercase;
  font-weight: 600;
}

.buttons-container .orange {
  background: #ff9800;
  color: #fff;
}

.buttons-container .active {
  transform: translate(1px, -1px);
}
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500,600&display=swap" rel="stylesheet">
<script src="https://unpkg.com/vue@next"></script>

<div class="container">
  <div class="calculator" id="myCalculator">
    <div class="display">
      <div class="track">
        {{track == '' ? ''  :  track + '=' }}
      </div>
      <div class="result">
        {{currentVal || 0}}
      </div>
    </div>
    <div class="buttons-container">
      <ol>
        <li @click="appendClicked('7')">7</li>
        <li @click="appendClicked('8')">8</li>
        <li @click="appendClicked('9')">9</li>
        <li @click="divide('&divide;')">&divide;</li>
        <li @click="appendClicked('4')">4</li>
        <li @click="appendClicked('5')">5</li>
        <li @click="appendClicked('6')">6</li>
        <li @click="multiply('&times;')">&times;</li>
        <li @click="appendClicked('1')">1</li>
        <li @click="appendClicked('2')">2</li>
        <li @click="appendClicked('3')">3</li>
        <li @click="subtract('-')">-</li>
        <li @click="appendClicked('0')">0</li>
        <li @click="appendDot('.')">&middot;</li>
        <li @click="add('+')">+</li>
        <li @click="equals" class="orange">=</li>
      </ol>
      <div @click="clearDisplay" class="clear orange">Clear</div>
    </div>
  </div>
</div>
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading