<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'
});
This Pen doesn't use any external CSS resources.