Created
June 7, 2018 18:14
-
-
Save Christilut/1143d453ea070f7e8fa345f7ada1b999 to your computer and use it in GitHub Desktop.
Vuetify Currency Field
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template lang="pug"> | |
v-text-field( | |
ref='field', | |
:prefix='prefix', | |
v-model='model', | |
@focus='onFocus', | |
@keyup='onKeyUp', | |
:error-messages='errorMessages', | |
v-bind='$attrs', | |
@change='onChange' | |
@blur='onBlur' | |
) | |
</template> | |
<script> | |
function tryParseFloat (str, defaultValue) { | |
var retValue = defaultValue | |
if (str !== null) { | |
if (str.length > 0) { | |
if (!isNaN(str)) { | |
retValue = parseFloat(str) | |
} | |
} | |
} | |
return retValue | |
} | |
export default { | |
props: { | |
value: null, | |
'error-messages': null, | |
allowNegative: { | |
type: Boolean, | |
default: false | |
}, | |
prefix: { | |
type: String, | |
default: '$ ' | |
}, | |
thousandsSeparator: { | |
type: String, | |
default: ',' | |
}, | |
decimalSeparator: { | |
type: String, | |
default: '.' | |
}, | |
languageCode: { | |
type: String, | |
default: 'en-US' | |
} | |
}, | |
data () { | |
return { | |
numberValue: this.value, | |
model: this.value, | |
isMasked: true, | |
thousandsSeparatorRegex: new RegExp(`\\${this.thousandsSeparator}`, 'g'), | |
decimalSeparatorRegex: new RegExp(`\\${this.decimalSeparator}`, 'g') | |
} | |
}, | |
methods: { | |
onFocus () { | |
this.isMasked = false | |
this.updateModel() | |
}, | |
onBlur () { | |
if (this.$listeners.blur) this.$listeners.blur() | |
this.isMasked = true | |
this.format() | |
}, | |
onKeyUp () { | |
this.updateNumberValue() | |
}, | |
onChange () { | |
if (this.$listeners.change) this.$listeners.change() | |
}, | |
updateNumberValue () { | |
let v = this.model | |
let parsed | |
v = v.replace(this.thousandsSeparatorRegex, '') | |
if (this.decimalSeparator !== '.') v = v.replace(this.decimalSeparatorRegex, this.thousandsSeparator) | |
const result = tryParseFloat(v) | |
if (!result) parsed = 0 | |
else parsed = result | |
if (!this.allowNegative && result < 0) parsed = 0 | |
this.numberValue = Math.round(parsed * 100) / 100 | |
}, | |
updateModel () { | |
if (this.numberValue === null) return | |
let v = this.numberValue.toString() | |
v = v.replace(this.thousandsSeparatorRegex, this.decimalSeparator) | |
this.model = v | |
}, | |
format () { | |
if (this.numberValue === null) return | |
let v = this.numberValue | |
v = v.toLocaleString(this.languageCode) | |
if (v.length !== 1 && v.slice(v.indexOf(this.decimalSeparator) + 1).length === 1) v += '0' | |
this.model = v | |
} | |
}, | |
watch: { | |
numberValue (v) { | |
this.$emit('input', v) | |
}, | |
value (v) { | |
this.numberValue = v | |
if (!this.$refs.field.isFocused) { | |
this.format() | |
} | |
} | |
}, | |
created () { | |
this.format() | |
} | |
} | |
</script> | |
<style lang="scss" scoped> | |
</style> |
Saved my day, thanks!
How to format to 10.000,00 ?
Because now is 10.000
Here is the code if anyone want to format currency onKeyup
`
<v-text-field
ref='field'
:prefix="prefix"
v-model="model"
@Focus="onFocus"
@keyup="onKeyUp"
:error-messages="errorMessages"
v-bind="$attrs"
@change="onChange"
@blur="onBlur"
<script> function tryParseFloat (str, defaultValue) { var retValue = defaultValue if (str !== null) { if (str.length > 0) { if (!isNaN(str)) { retValue = parseFloat(str) } } } return retValue } export default { props: { value: null, 'error-messages': null, allowNegative: { type: Boolean, default: false }, maxNumber : { type : Number, default: 5, }, prefix: { type: String, default: '$ ' }, thousandsSeparator: { type: String, default: ',' }, decimalSeparator: { type: String, default: '.' }, languageCode: { type: String, default: 'en-US' } }, data () { return { numberValue: this.value, model: this.value, isMasked: true, thousandsSeparatorRegex: new RegExp(`\\${this.thousandsSeparator}`, 'g'), decimalSeparatorRegex: new RegExp(`\\${this.decimalSeparator}`, 'g') } }, methods: { maskInput(){ return "#".repeat(this.maxNumber); }, onFocus () { //x this.updateModel() }, onBlur () { if (this.$listeners.blur) this.$listeners.blur() this.isMasked = true this.format() }, onKeyUp (event) { if(isNaN(String.fromCharCode(event.which))) { event.preventDefault(); //stop character from entering input } this.updateNumberValue(); this.format(); }, onChange () { if (this.$listeners.change) this.$listeners.change() }, updateNumberValue () { let v = this.model let parsed v = v.replace(this.thousandsSeparatorRegex, '') if (this.decimalSeparator !== '.') v = v.replace(this.decimalSeparatorRegex, this.thousandsSeparator) const result = tryParseFloat(v) if (!result) parsed = 0 else parsed = result if (!this.allowNegative && result < 0) parsed = 0 this.numberValue = Math.round(parsed * 100) / 100 }, updateModel () { if (this.numberValue === null) return let v = this.numberValue.toString() v = v.replace(this.thousandsSeparatorRegex, this.decimalSeparator) this.model = v }, format () { if (this.numberValue === null) return let v = this.numberValue v = v.toLocaleString(this.languageCode) if (v.length !== 1 && v.slice(v.indexOf(this.decimalSeparator) + 1).length === 1) v += '0' this.model = v } }, watch: { numberValue (v) { this.$emit('input', v) }, value (v) { this.numberValue = v if (!this.$refs.field.isFocused) { this.format() } } }, created () { this.format() } } </script> <style lang="scss" scoped> </style>`
Is there a way to restrict alphabets on change/input?
Hello @Christilut!
Thank you for this gist.
I made a mod to support precision numbers greater than 2.
props:{
//....
precision:{
type: Number,
default: 2
}
}
in data add nprecision
data() {
return {
//...
nprecision: this.precision,
//...
}
}
at the methods add a new method roundNumber, in "updateNumberValue" change Math.round call to "this.roundNumber(parsed, this.nprecision)" and alter "format" methods add a new parameter to v.toLocaleToString
methods:{
roundNumber(num, scale) {
//https://stackoverflow.com/a/12830454/4537233
if(!("" + num).includes("e")) {
return +(Math.round(num + "e+" + scale) + "e-" + scale);
} else {
var arr = ("" + num).split("e");
var sig = ""
if(+arr[1] + scale > 0) {
sig = "+";
}
return +(Math.round(+arr[0] + "e" + sig + (+arr[1] + scale)) + "e-" + scale);
}
},
updateNumberValue () {
let v = this.model
let parsed
v = v.replace(this.thousandsSeparatorRegex, '')
if (this.decimalSeparator !== '.') v = v.replace(this.decimalSeparatorRegex, this.thousandsSeparator)
const result = tryParseFloat(v)
if (!result) parsed = 0
else parsed = result
if (!this.allowNegative && result < 0) parsed = 0
this.numberValue = this.roundNumber(parsed, this.nprecision); //Math.round(parsed * 100) / 100
}
//....
format () {
if (this.numberValue === null) return
let v = this.numberValue
v = v.toLocaleString(this.languageCode, {maximumFractionDigits:this.nprecision})
if (v.length !== 1 && v.slice(v.indexOf(this.decimalSeparator) + 1).length === 1) v += '0'
this.model = v
}
Best!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage just like VTextField: