<div id="app">
  <commissions>My Commissions</commissions>
</div>
.row {padding: 15px;}
.title{
  font-size: 22px;
  font-weight: bold;
}
//Create your component. For real dev use .vue files ;)
Vue.component('commissions',{
  //Template. Each field has event listener for @focus and @blur
  //On focus, the number is unformatted to permit speed of typing
  //On blur, we format the number
  //The field named net is read only becaues it equals  gross - tax 
  template: `
    <div>
      <form action="" id="form">
        <div class="title"><slot></slot></div>
        <div class="row">
        <label for="gross">Gross:</label>    
       <input @focus="unsetFormatNumeric('grossCommissions')" @blur="setFormatNumeric('grossCommissions')" name="gross" type="text" v-model="grossCommissions" style="text-align: right"/>
      </div>
      <div class="row">  
        <label for="tax">Tax:</label>
        <input @focus="unsetFormatNumeric('tax')" @blur="setFormatNumeric('tax')" name="tax" type="text" v-model="tax" style="text-align: right">
      </div>
      <div class="row">
        <label for="net">Net:</label>
        <input readonly name="net" v-model="netCommissions" style="text-align: right"/>
      </div>
      </form>
    </div>
  `,
  //The items suffixed Numeral will hold the real numbers
  //curencyFormat is setting for the required format to
  //be used by numeral.js for a particular field
  data: function() {
    return {
      grossCommissionsNumeral: undefined,
      taxNumeral:  undefined,
      netCommissionsNumeral: undefined,
      currencyFormat: {}      
    }
  },
  //getter formats the number nicely
  //setter stores it in data variable mapped to the field
  computed: {
    grossCommissions: {
      get() {
        
        return this.getNumeralFormatted(
          this.grossCommissionsNumeral, 'grossCommissions'
        );
      },
      set(val) {
          this.grossCommissionsNumeral = this.getNumeralUnformatted(val);
      }
    },
    tax: {
      get() {
        return this.getNumeralFormatted(
          this.taxNumeral, 'tax'
        );        
      },
      set(val) {
          this.taxNumeral = this.getNumeralUnformatted(val);        
      }
    },
    netCommissions() {  
      if (
        isNaN(this.grossCommissionsNumeral)
        || isNaN(this.taxNumeral)
      ) {
        return null;
      }
      
      this.netCommissionsNumeral = this.grossCommissionsNumeral - this.taxNumeral;
      return this.getNumeralFormatted(this.netCommissionsNumeral, 'netCommissions');
    }
    
  },
  methods: {
          setFormatNumeric(fieldName){
            this.currencyFormat[(fieldName)] = "#,##0.00";
          },
          unsetFormatNumeric(fieldName) {
            this.currencyFormat[(fieldName)] = "###0.00";
          },
          getNumeralFormatted(val, fieldName) {
            if (
                Number.parseFloat(val) == 0
                || val == undefined
                || val == null
            ) {
                return null;
            } else {
                return numeral(val).format(this.currencyFormat[(fieldName)]);
            }
          },
          getNumeralUnformatted(val) {
            const number = +val.toString().replace(/[^\d.,]/g, '');
            return isNaN(number) ? 0 : parseFloat(number.toFixed(2));    
          }   },
  created() {
     this.currencyFormat = {
       'grossCommissions': "0,0.00",
       'tax': '0,0.00',
       'netCommissions' : "0,0.00",
     };    
  },
  //create the default currency format for all fields
   mounted() {
      if (numeral.locales['en-ch'] === undefined) {
        numeral.register("locale", "en-ch", {
          delimiters: {
            thousands: "'",
            decimal: "."
          },
          abbreviations: {
            thousand: "k",
            million: "m",
            billion: "b",
            trillion: "t"
          },
          currency: {
            symbol: "CHF" 
          }
        });
      }

      numeral.locale('en-ch');      
   }
});

const vm = new Vue({
    el: '#app'
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdn.jsdelivr.net/npm/vue/dist/vue.js
  2. https://cdnjs.cloudflare.com/ajax/libs/numeral.js/2.0.6/numeral.min.js