dm4t2 / vue-currency-input Goto Github PK
View Code? Open in Web Editor NEWEasy input of currency formatted numbers for Vue.js.
Home Page: https://dm4t2.github.io/vue-currency-input/
License: MIT License
Easy input of currency formatted numbers for Vue.js.
Home Page: https://dm4t2.github.io/vue-currency-input/
License: MIT License
This is more or less the same issue as #6.
Passing a float value to an input field with v-currency directive formats the display value wrong:
Input: 4500.45
Display on blur: 450.045,00 €
I've seen that you are using Intl.NumberFormat for formatting, which actually seems to work quite well.
Just using:
new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(4500.45)
correctly returns:
4.500,45 €
Might there be an issue as the value is beeing formatted twice?
https://github.com/dm4t2/vue-currency-input/blob/master/src/directive.js#L103
and
https://github.com/dm4t2/vue-currency-input/blob/master/src/directive.js#L105
All validation returns false.
I guess it has something to do with:
https://baianat.github.io/vee-validate/examples/custom-component.html
-> Must emit an input event whenever the value changes.
For example the number 200.00 could be displayed as 200, but the number 200.20 would still be displayed as 200.20. Basically what "Hide negligible decimal digits" currently does, but without focus. It would be useful for example for online stores where most prices (but not all) are whole numbers such as $7.
Hi, thanks for creating this component.
I was wondering if it would be possible to add in a prop
to specify that you want to pass in and retrieve the model as an integer, as usually when working with money it is considered best practice to work with the factional part of the currency and always store an integer. Something like :valueAsInteger="true"
.
I'd originally achieved this by wrapping the component and causing the set on a computed property to run the following code:
let valueInCents = 0;
if (value !== null) {
valueInCents = Number.isInteger(value)
? value * 100
: parseInt((`${value}`).replace('.', ''), 10);
}
this.$emit('input', valueInCents);
But this was causing the components to enter an infinite loop growing this.value
.
Alternatively, perhaps you could give me some pointers on where to start if I were to try to attempt a PR that attempted this feature.
Thank you for your time.
Awesome package. But I just noticed negative values don't seem to work when the locale is set to nl-NL
. It always returns the positive value.
I've tried with some other locales (be-NL, de-DE, es-ES...) and they all seem to work. The only difference I've found so far is nl-NL adds a space between the symbol and the value. For example: € 23,54
.
I'm using the latest version (1.8.3). Thanks in advance!
Should you try to change the currency/locale to EUR/el
in the directive example: https://github.com/dm4t2/vue-currency-input/blob/master/docs/.vuepress/components/RawNumberValueWithDirective.vue the following happens:
Trying to enter the decimal digits, after entering a comma keystroke, will only accept the first digit correctly. If you enter a second one, the end amount (once you focus out of the input field) is wrong.
Examples:
Type: 100,1 , tab out shows 100,10 €
Type: 100,15 , tab out shows 10.015,00 €
The issue doesn't occur when using locales based on the dot
decimal separator.
1,222,333.22=>1222333.22
The component props link is broken here: https://dm4t2.github.io/vue-currency-input/guide/#usage
In our situation, we don't want to register the plugin globally as most of the pages are not using it. Therefore we go with directive solution which allows you to import this currency input on demand. However, this means we need to implement our own parseCurrency method and we can't config the default currency and locale (The default locale configuration is passed in as a parameter when the library is registered globally). When we creating our own parseCurrency
function, we find that parse
and createCurrencyFormat
in the parseCurrency
implementation is not exported.
I have created a pull request to export these two functions. #26
This is by far the easiest plugin I've tried so far for currency formatting so thank you for the time and effort you've put into it. With that said, I'm running into an issue where when I highlight a value and delete it or delete the value one character at a time until there's nothing left, then click out of the input, the input field is blank.
I'm using Vuex and I've tried multiple methods of trying to force the input field to maintain a 0 value when it has lost focus, but so far have had no luck. Is there a way to maintain a default value of 0 when the field is cleared?
Thanks!
Rick
Hi,
First of all, thank you for providing this library.
I just found out that a Vue project created with @vue/cli that uses vue-currency-input breaks in Internet explorer 11 and in Microsoft Edge with the following error
"Expected identifier, string or number"
The way to reproduce the problem is simple.
create a new project with vue with the defaults. Follow the instructions in https://dm4t2.github.io/vue-currency-input/guide/ to add Vue Currency to the project, run the project with yarn serve and open the url with IE 11 or MS Edge.
This kind of errors is usually caused by a trailing comma somewhere, but wasn't able to find one.
Best regards,
Rodrigo
If a currency symbol is suffixed the field’s content cannot be deleted via the backspace key if the cursor is positioned to the right of the symbol and distraction-free
is set to false
. Ideally the backspace key would just ignore the suffixed symbol and delete the last digit of the input.
I'm using a computed value with get & set, whenever a set is done, the directive doesn't see the change (when the set is done outside the directive) and simply puts the value to the number without a format. Would it be possible to add a watch on the v-model of the directive that formats the value (if it isn't focused etc)?
Is it possible to currency symbol all of the time, but retain locale information for the rest of the formatted number.
Hello 👋🏻
It would be great if you can add some more flexibility to number formatting.
In my case I no need any digit separators at all:
1 234 567.1235678
-> 1 234 567.1235678
.
But if the decimal part is empty, then no need to show trailing zeros:
12345.00000000
-> 12345
.
Thank you!
Hi, Vue Currency Input is awesome, but I've just noticed that passing distraction-free
option into global configuration and component itself is not working . The one in the example doesn't also work or am I missing something ?
Hi, I tried to get raw value in directive but I don't know how to get it.
Is possible this in the directive?
It is not possible to set null value in the v-model when min property is passed.
Would love to see a config option to turn the formatting on or off (like disable: true/false).
I tried using it via CDN link provided
<script src="https://unpkg.com/vue-currency-input"></script>I am getting following error
Uncaught ReferenceError: Vue is not defined
at eval (eval at (eval at (dojo.js?v=1:341)), :7:15209)
at runFactory (dojo.js?v=1:1120)
at execModule (dojo.js?v=1:1249)
at execModule (dojo.js?v=1:1240)
at dojo.js?v=1:1284
at guardCheckComplete (dojo.js?v=1:1264)
at checkComplete (dojo.js?v=1:1279)
at onLoadCallback (dojo.js?v=1:1439)
at HTMLScriptElement.onLoad (dojo.js?v=1:1675)
It is pointing to this line
(r=i.currency),u(e,l(t,r))}}};"undefined"!=typeof window&&window.Vue&&window.Vue.use(x)}(Vue);
Hi, great component, but I'd love to be able to turn off the currency symbol entirely. that way I can align my other input types (percent, text etc..) using custom symbols.
Hi,
I want to know how I can format the decimal and thousand symbol by myself.
I need a format like this:
15'251.95 CHF
Any tips for me?
Thank you
Hi
How can i set decimal place length default is 2 , i need to set it 4
Thanks.
Hello,
I just switched from "vue-currency-input": "1.3.2"
to "vue-currency-input": "1.5.0"
Now I am getting this error:
ReferenceError: Can't find variable: Vue
Seems to be this line:
/* WEBPACK VAR INJECTION */(function(global) {!function(o){"use strict";o=o&&o.hasOwnProperty("default")?o.default:o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;var e,t,r=(function(e,t){e.exports=function(r){function n(e){if(o[e])return o[e].exports;var t=o[e]={exports:{},id:e,loaded:!1};return r[e].call(t.exports,t,t.exports,n),t.loaded=!0,t.exports}var o={};return n.m=r,n.c=o,n.p="",n(0)}([function(e,t,r){function n(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=r(3);Object.defineProperty(t,"conformToMask",{enumerable:!0,get:function(){return n(o).default}});var i=r(2);Object.defineProperty(t,"adjustCaretPosition",{enumerable:!0,get:function(){return n(i).default}});var a=r(5);Object.defineProperty(t,"createTextMaskInputElement",{enumerable:!0,get:function(){return n(a).default}})},function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.placeholderChar="_",t.strFunction="function"},function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){var t=e.previousConformedValue,r=void 0===t?U:t,n=e.previousPlaceholder,o=void 0===n?U:n,i=e.currentCaretPosition,a=void 0===i?0:i,u=e.conformedValue,l=e.rawValue,s=e.placeholderChar,c=e.placeholder,f=e.indexesOfPipedChars,d=void 0===f?D:f,p=e.caretTrapIndexes,v=void 0===p?D:p;if(0===a||!l.length)return 0;var m=l.length,h=r.length,y=c.length,g=u.length,b=m-h,x=0<b,C=0===h;if(1<b&&!x&&!C)return a;var O=0,w=void 0,S=void 0;if(!x||r!==u&&u!==c){var _=u.toLowerCase(),T=l.toLowerCase().substr(0,a).split(U).filter(function(e){return-1!==_.indexOf(e)});S=T[T.length-1];var P=o.substr(0,T.length).split(U).filter(function(e){return e!==s}).length,k=c.substr(0,T.length).split(U).filter(function(e){return e!==s}).length!==P,E=void 0!==o[T.length-1]&&void 0!==c[T.length-2]&&o[T.length-1]!==s&&o[T.length-1]!==c[T.length-1]&&o[T.length-1]===c[T.length-2];!x&&(k||E)&&0<P&&-1<c.indexOf(S)&&void 0!==l[a]&&(w=!0,S=l[a]);for(var $=d.map(function(e){return _[e]}).filter(function(e){return e===S}).length,N=T.filter(function(e){return e===S}).length,V=c.substr(0,c.indexOf(s)).split(U).filter(function(e,t){return e===S&&l[t]!==e}).length+N+$+(w?1:0),F=0,M=0;M<g;M++){var j=_[M];if(O=M+1,j===S&&F++,V<=F)break}}else O=a-b;if(x){for(var I=O,A=O;A<=y;A++)if(c[A]===s&&(I=A),c[A]===s||-1!==v.indexOf(A)||A===y)return I}else if(w){for(var R=O-1;0<=R;R--)if(u[R]===S||-1!==v.indexOf(R)||0===R)return R}else for(var L=O;0<=L;L--)if(c[L-1]===s||-1!==v.indexOf(L)||0===L)return L};var D=[],U=""},function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0});var D="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};t.default=function(){var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:B,t=1<arguments.length&&void 0!==arguments[1]?arguments[1]:q,r=2<arguments.length&&void 0!==arguments[2]?arguments[2]:{};if(!(0,U.isArray)(t)){if((void 0===t?"undefined":D(t))!==W.strFunction)throw new Error("Text-mask:conformToMask; The mask property must be an array.");t=t(e,r),t=(0,U.processCaretTraps)(t).maskWithoutCaretTraps}var n=r.guide,o=void 0===n||n,i=r.previousConformedValue,a=void 0===i?B:i,u=r.placeholderChar,l=void 0===u?W.placeholderChar:u,s=r.placeholder,c=void 0===s?(0,U.convertMaskToPlaceholder)(t,l):s,f=r.currentCaretPosition,d=r.keepCharPositions,p=!1===o&&void 0!==a,v=e.length,m=a.length,h=c.length,y=t.length,g=v-m,b=0<g,x=f+(b?-g:0),C=x+Math.abs(g);if(!0===d&&!b){for(var O=B,w=x;w<C;w++)c[w]===l&&(O+=l);e=e.slice(0,x)+O+e.slice(x,v)}for(var S=e.split(B).map(function(e,t){return{char:e,isNew:x<=t&&t<C}}),_=v-1;0<=_;_--){var T=S[_].char;T!==l&&T===c[x<=_&&m===y?_-g:_]&&S.splice(_,1)}var P=B,k=!1;e:for(var E=0;E<h;E++){var $=c[E];if($===l){if(0<S.length)for(;0<S.length;){var N=S.shift(),V=N.char,F=N.isNew;if(V===l&&1!=p){P+=l;continue e}if(t[E].test(V)){if(!0===d&&!1!==F&&a!==B&&!1!==o&&b){for(var M=S.length,j=null,I=0;I<M;I++){var A=S[I];if(A.char!==l&&!1===A.isNew)break;if(A.char===l){j=I;break}}null!==j?(P+=V,S.splice(j,1)):E--}else P+=V;continue e}k=!0}0==p&&(P+=c.substr(E,h));break}P+=$}if(p&&0==b){for(var R=null,L=0;L<P.length;L++)c[L]===l&&(R=L);P=null!==R?P.substr(0,R+1):B}return{conformedValue:P,meta:{someCharsRejected:k}}};var U=r(4),W=r(1),q=[],B=""},function(e,t,r){function n(e){return Array.isArray&&Array.isArray(e)||e instanceof Array}Object.defineProperty(t,"__esModule",{value:!0}),t.convertMaskToPlaceholder=function(){var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:i,t=1<arguments.length&&void 0!==arguments[1]?arguments[1]:o.placeholderChar;if(!n(e))throw new Error("Text-mask:convertMaskToPlaceholder; The mask property must be an array.");if(-1===e.indexOf(t))return e.map(function(e){return e instanceof RegExp?t:e}).join("");throw new Error("Placeholder character must not be used as part of the mask. Please specify a character that is not present in your mask as your placeholder character.\n\nThe placeholder character that was received is: "+JSON.stringify(t)+"\n\nThe mask that was received is: "+JSON.stringify(e))},t.isArray=n,t.isString=function(e){return"string"==typeof e||e instanceof String},t.isNumber=function(e){return"number"==typeof e&&void 0===e.length&&!isNaN(e)},t.isNil=function(e){return null==e},t.processCaretTraps=function(e){for(var t=[],r=void 0;-1!==(r=e.indexOf(a));)t.push(r),e.splice(r,1);return{maskWithoutCaretTraps:e,indexes:t}};var o=r(1),i=[],a="[]"},function(e,t,r){function n(e){return e&&e.__esModule?e:{default:e}}function N(e){if((0,I.isString)(e))return e;if((0,I.isNumber)(e))return String(e);if(null==e)return R;throw new Error("The 'value' provided to Text Mask needs to be a string or a number. The value received was:\n\n "+JSON.stringify(e))}Object.defineProperty(t,"__esModule",{value:!0});var V=Object.assign||function(e){for(var t=arguments,r=1;r<arguments.length;r++){var n=t[r];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e},F="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};t.default=function(E){var $={previousConformedValue:void 0,previousPlaceholder:void 0};return{state:$,update:function(e){var t,r,n=1<arguments.length&&void 0!==arguments[1]?arguments[1]:E,o=n.inputElement,i=n.mask,a=n.guide,u=n.pipe,l=n.placeholderChar,s=void 0===l?A.placeholderChar:l,c=n.keepCharPositions,f=void 0!==c&&c,d=n.showMask,p=void 0!==d&&d;if(void 0===e&&(e=o.value),e!==$.previousConformedValue){(void 0===i?"undefined":F(i))===D&&void 0!==i.pipe&&void 0!==i.mask&&(u=i.pipe,i=i.mask);var v=void 0,m=void 0;if(i instanceof Array&&(v=(0,I.convertMaskToPlaceholder)(i,s)),!1!==i){var h=N(e),y=o.selectionEnd,g=$.previousConformedValue,b=$.previousPlaceholder,x=void 0;if((void 0===i?"undefined":F(i))===A.strFunction){if(!1===(m=i(h,{currentCaretPosition:y,previousConformedValue:g,placeholderChar:s})))return;var C=(0,I.processCaretTraps)(m);m=C.maskWithoutCaretTraps,x=C.indexes,v=(0,I.convertMaskToPlaceholder)(m,s)}else m=i;var O={previousConformedValue:g,guide:a,placeholderChar:s,pipe:u,placeholder:v,currentCaretPosition:y,keepCharPositions:f},w=(0,j.default)(h,m,O).conformedValue,S=(void 0===u?"undefined":F(u))===A.strFunction,_={};S&&(!1===(_=u(w,V({rawValue:h},O)))?_={value:g,rejected:!0}:(0,I.isString)(_)&&(_={value:_}));var T=S?_.value:w,P=(0,M.default)({previousConformedValue:g,previousPlaceholder:b,conformedValue:T,placeholder:v,rawValue:h,currentCaretPosition:y,placeholderChar:s,indexesOfPipedChars:_.indexesOfPipedChars,caretTrapIndexes:x}),k=T===v&&0===P?p?v:R:T;$.previousConformedValue=k,$.previousPlaceholder=v,o.value!==k&&(o.value=k,t=o,r=P,document.activeElement===t&&(U?W(function(){return t.setSelectionRange(r,r,L)},0):t.setSelectionRange(r,r,L)))}}}}};var o=r(2),M=n(o),i=r(3),j=n(i),I=r(4),A=r(1),R="",L="none",D="object",U="undefined"!=typeof navigator&&/Android/i.test(navigator.userAgent),W="undefined"!=typeof requestAnimationFrame?requestAnimationFrame:setTimeout}])}(e={exports:{}},e.exports),e.exports);(t=r)&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")&&t.default;function h(e){return e.replace(/\D+/g,"")}function y(e,t){return t&&e.startsWith(t)?e.substr(t.length):e}function g(e,t){return t&&e.endsWith(t)?e.slice(0,-1*t.length):e}function u(e,t){void 0===t&&(t={});var r=t.prefix,n=t.suffix,o=t.thousandsSeparatorSymbol,i=t.decimalSymbol;if("number"==typeof e)return e;if(e&&"string"==typeof e){if(e.match(/^-?\d+(\.\d+)?$/))return Number(e);var a=e.startsWith("-");e=y(e,"-"),e=y(e,r);var u=(e=g(e,n)).split(i);if(2<u.length)return null;var l=u[0].replace(new RegExp("."===o?"\\.":o,"g"),"");if(l.length&&!l.match(/^\d+$/g))return null;var s=l;if(2===u.length){var c=u[1];if(c.length&&!c.match(/^\d+$/g))return null;s+="."+c}if(s)return a&&(s="-"+s),s=Number(s),Number.isNaN(s)?null:s}return null}function b(e){return e.split("").map(function(e){return n.test(e)?n:e})}var i=r.createTextMaskInputElement,a=(r.textMaskCore,{locale:void 0,currency:"EUR",distractionFree:!0,min:null,max:null,validateOnInput:!1}),n=/\d/;function l(e,t){var r=new Intl.NumberFormat(e,{style:"currency",currency:t}).format(1234),n=(r.match(/0/g)||[]).length,o=0<n?r.substr(r.indexOf("4")+1,1):null,i=null!==o;return{prefix:r.substring(0,r.indexOf("1")),suffix:r.substring(r.lastIndexOf(0<n?"0":"4")+1),thousandsSeparatorSymbol:r.substr(r.indexOf("1")+1,1),decimalSymbol:o,decimalLimit:n,allowDecimal:i}}var s={bind:function(e,t){var n=f(e,t.value);o.nextTick(function(){n.value&&d(n)}),n.addEventListener("input",function(){p(n)},{capture:!0}),n.addEventListener("format",function(e){var t=e.detail;n.$ci.focus||(p(n,t.value),n.dispatchEvent(new Event("format-complete")))}),n.addEventListener("focus",function(){var e=n.$ci,t=e.options,r=e.currencyFormatConfig;n.$ci.focus=!0,t.distractionFree&&setTimeout(function(){var e=v(n);p(n,u(n.value,r)),n.setSelectionRange(e,e)},0)}),n.addEventListener("blur",function(){n.$ci.focus=!1,d(n)})},componentUpdated:function(e,t){if(t.value&&c(t.oldValue,t.value)){var r=f(e,t.value);d(r,r.$ci.numberValue)}}},c=function(t,r){return Object.keys(a).some(function(e){return t[e]!==r[e]})},f=function(e,t){var r=e.matches("input")?e:e.querySelector("input");if(!r)throw new Error("The directive must be applied on an element consists of an input element");var n=Object.assign({},o.prototype.$CI_DEFAULT_OPTIONS||a,t);if(null!=n.min&&null!=n.max&&n.min>n.max)throw new Error("Invalid number range");return r.$ci=Object.assign({},r.$ci||{},{options:n,currencyFormatConfig:l(n.locale,n.currency),textMaskInputElement:i({inputElement:r,mask:[]})}),r},d=function(e,t){void 0===t&&(t=u(e.value,e.$ci.currencyFormatConfig)),null==t||e.$ci.currencyFormatConfig.allowDecimal||(t=Math.round(t)),p(e,t),e.dispatchEvent(new Event("input"))},p=function(e,t,r){void 0===t&&(t=e.value),void 0===r&&(r=e.$ci);var n=r.options,o=r.currencyFormatConfig,i=r.textMaskInputElement,a=r.focus&&n.distractionFree;"number"==typeof t&&(null!=n.min&&t<n.min&&(t=n.min),null!=n.max&&t>n.max&&(t=n.max),t=new Intl.NumberFormat(n.locale,{minimumFractionDigits:a?0:o.decimalLimit}).format(t),n.distractionFree&&(t+=" ")),i.update(t,{inputElement:e,pipe:function(e,t){var r=t.previousConformedValue;if(n.validateOnInput){if(null!=n.min&&u(e,o)<n.min)return r;if(null!=n.max&&u(e,o)>n.max)return r}return e},mask:function(e){void 0===e&&(e={});var u=e.prefix,l=e.suffix,s=e.thousandsSeparatorSymbol,c=e.allowDecimal,f=e.allowNegative,d=e.decimalSymbol,p=e.decimalLimit,v=u?u.length:0,m=l?l.length:0;return function(e){void 0===e&&(e="");var t,r,n=-1!==e.indexOf(d),o=e.startsWith("-")&&f;if(e=y(e,"-"),e=y(e,u),e=g(e,l),n&&c){var i=e.split(d);t=i[0],r=b(h(i[1]))}else t=e;t=(t=(t=h(t)).replace(/^0+(0$|[^0])/,"$1")).replace(/\B(?=(\d{3})+(?!\d))/g,s);var a=b(t);return n&&c&&(a.push("[]",d,"[]"),r&&("number"==typeof p&&(r=r.slice(0,p)),a=a.concat(r))),0<v&&(a=u.split("").concat(a)),o&&(a=[/-/].concat(a)),0<m&&(a=a.concat(l.split(""))),a}}(Object.assign({},o,{prefix:a?"":o.prefix,suffix:a?"":o.suffix,thousandsSeparatorSymbol:a?"":o.thousandsSeparatorSymbol,allowNegative:null===n.min&&null===n.max||n.min<0||n.max<0}))}),e.$ci.numberValue=u(e.value,o)},v=function(e,t){void 0===t&&(t=e.$ci.currencyFormatConfig);var r=t.prefix,n=t.thousandsSeparatorSymbol;return Math.max(0,e.selectionStart-r.length-(e.value.substring(0,e.selectionStart).match(new RegExp("."===n?"\\.":n,"g"))||[]).length)};var m=function(e,t,r,n,o,i,a,u,l,s){"boolean"!=typeof a&&(l=u,u=a,a=!1);var c,f="function"==typeof r?r.options:r;if(e&&e.render&&(f.render=e.render,f.staticRenderFns=e.staticRenderFns,f._compiled=!0,o&&(f.functional=!0)),n&&(f._scopeId=n),i?(c=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),t&&t.call(this,l(e)),e&&e._registeredComponents&&e._registeredComponents.add(i)},f._ssrRegister=c):t&&(c=a?function(){t.call(this,s(this.$root.$options.shadowRoot))}:function(e){t.call(this,u(e))}),c)if(f.functional){var d=f.render;f.render=function(e,t){return c.call(t),d(e,t)}}else{var p=f.beforeCreate;f.beforeCreate=p?[].concat(p,c):[c]}return r}({render:function(){var e=this,t=e.$createElement;return(e._self._c||t)("input",e._g({directives:[{name:"currency",rawName:"v-currency",value:e.options,expression:"options"}],domProps:{value:e.formattedValue}},e.listeners()))},staticRenderFns:[]},void 0,{name:"CurrencyInput",directives:{currency:s},props:{value:{type:Number,default:null},locale:{type:String,default:void 0},currency:{type:String,default:void 0},distractionFree:{type:Boolean,default:void 0},min:{type:Number,default:void 0},max:{type:Number,default:void 0},validateOnInput:{type:Boolean,default:void 0}},data:function(){return{formattedValue:this.value}},computed:{options:function(){var t=this,r=Object.assign({},this.$CI_DEFAULT_OPTIONS||a);return Object.keys(r).forEach(function(e){void 0!==t[e]&&(r[e]=t[e])}),r},currencyFormatConfig:function(){return l(this.options.locale,this.options.currency)}},watch:{value:function(e){this.$el.dispatchEvent(new CustomEvent("format",{detail:{value:e}}))}},methods:{listeners:function(){var e=this;return Object.assign({},this.$listeners,{input:function(){return e.emitValue()},"format-complete":function(){return e.emitValue()}})},emitValue:function(){this.$emit("input",u(this.$el.value,this.currencyFormatConfig)),this.formattedValue=this.$el.value}}},void 0,!1,void 0,void 0,void 0),x={install:function(e,t){void 0===t&&(t={});var r=t.componentName;void 0===r&&(r=m.name);var n=t.directiveName;void 0===n&&(n="currency");var o=t.globalOptions;void 0===o&&(o={});var i=Object.assign({},a,o);e.prototype.$CI_DEFAULT_OPTIONS=i,e.component(r,m),e.directive(n,s),e.prototype.$parseCurrency=function(e,t,r){return void 0===t&&(t=i.locale),void 0===r&&(r=i.currency),u(e,l(t,r))}}};"undefined"!=typeof window&&window.Vue&&window.Vue.use(x)}(Vue);
Version 1.3.2
still works fine.
This is how I implemented it:
import Vue from 'vue'
import VueCurrencyInput from 'vue-currency-input'
Vue.use (VueCurrencyInput);
I am trying to use the global options like this:
import Vue from 'vue'
import VueCurrencyInput from 'vue-currency-input'
Vue.use(VueCurrencyInput, {
globalOptons : {
currency : 'USD',
distractionFree : false,
min : 0,
validateOnInput : true
}
})
I tried using both the <currency-input />
as well as the directive, but my input continues to use the default options:
If I set the options directly on the input, then it works properly:
Am I misconfiguring this somehow? I double checked and I am on version 1.4.1 which should have the ability to use the globalOptions
.
I'm using the v-currency directive with vue-material input components:
<md-field>
<label>Home Price</label>
<md-input v-model="price" v-currency @focus.native="$event.target.select()"></md-input>
</md-field>
with the v-currency directive added to the component, @focus.native does not work to select all text. If I remove the v-currency directive, the input selects all text as expected.
@click.native="$event.target.select()" does work correctly when clicking into the input to bring focus, all text is selected. It's only when pressing the tab key to bring focus.
Hello,
actually I really like this component.
But: The handling of float values is broken. You can see this in your example:
Value, that is set: 1234.5 (https://github.com/dm4t2/vue-currency-input/blob/master/docs/.vuepress/components/ComponentDemo.vue#L91)
Value that is shown: 12.345,00 $ (https://dm4t2.github.io/vue-currency-input/demo/)
Raw number value: 12345
I would love to see a patch :-)
Simply getting this error message, might be a TS issue:
Module '"/node_modules/vue-currency-input/src/index"' has no default export.
Hello everybody,
I got this object, which is loaded via API before the page is rendered:
{ "id": 1, "title": "Test", "price": 9, "setup": 0}
Now if I add this to my Vue project:
<currency-input id="product-price"
name="product-price"
v-validate="'required'"
:class="{'form-control': true, 'is-invalid': errors.has('product-price')}"
:currency="currency"
v-model="product.price"/>
I am getting no value - product.price
is empty now:
{ "id": 1, "title": "Test", "price": null, "setup": 0}
If I remove the currency-input
, the object is correct again:
{ "id": 1, "title": "Test", "price": 9, "setup": 0}
can you add option for hide currency from input please?
Now I base on Element UI
.
Could I use this as directive
<el-input v-model="value" v-currency="opts" />
--------
import CurrencyInput from 'vue-currency-input'
export default {
directives: { currency: CurrencyInput },
data: () => ({
value: 1000,
opts: {
currency: 'USD',
allow-negative:...,
decimal: .....,
}
})
}
vue-currency-input is not working when precision is set as object and min is set to 0 or null:
{ min: 0, max: 2}
I live this plugin.
I try to using nuxt.js environment.
Everything is ok. But, $parseCurrency
occur error.
The problem seems to be Vue.prototype
.
How about using mixin
.
Good decimal plugin. ^^
I have a option to change the currency and a max value for my currency field.
If I change the currency or reach the max value, everything is working fine and looks good but it does not safe the updated data. Even with watch.
That's a big issue because It saves old and unusable data for me.
My field looks like this:
<input type="text" class="small" v-currency="{ currency: selectedCurrency, locale, distractionFree: false, min: currency.min, max: currency.max, }" v-model="$parent.$parent.fields.investmentAmount" />
my locale
value is computed.
Hello!
Love your plugin, but I feel like a RTL option would make it perfect. Let me give you an example:
Do you think it's possible to make this enhancement?
Hi!
I have a form with two inputs - min and max and an 'onInput' event handler, that calls an api to update data.
My issue is when i blurring input, the plugin dispatches additional input event and my api is calling twice.
I have several checks if values from input not changed, but in some cases that don't work.
I'm using plugin as a component.
Here is my configuration:
const pluginOptions = {
globalOptions: {
currency: null,
distractionFree: false,
decimalLength: 0
}
}
Vue.use(VueCurrencyInput, pluginOptions)
Example of using component
<currency-input type="tel" name="min"
v-model="priceInput.min"
:placeholder="allFacets.price[1].value | thousandSeparator"
:data-min="allFacets.price[1].value"
ref="minPrice"
@input="handlePriceInput"
autocomplete="off"
class="digi-price-input"
></currency-input>
I notice in vue-dev-tools, that blurring input causes two 'input' events.
I think that in distractionFree: false
mode is not necessarily dispatch input event in onBlur handler.
line 55 in directive.js
Vue - 2.6.10
vue-currency-input - 1.11.3
PS: if you want, i can create a minimal reproduction of this.
This would be a cool feature. You have to keep in mind that not every language has 2 fraction digits. Regarding to this list: https://www.currency-iso.org/dam/downloads/lists/list_one.xml there are several currencies with 3 or 4 fraction digits. A very nice feature would be to set the property valueAsInteger
and parses it based on the minimumFractionDigit
Option of the Intl.NumberFormat
const formatter = new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(number)
const options = formatter.resolvedOptions()
let valueInCents = 0;
if (value !== null) {
valueInCents = Number.isInteger(value)
? value * Math.pow(10, options.minimumFractionDigits)
: parseInt((`${value}`).replace('.', ''), 10);
}
this.$emit('input', valueInCents);
Edit: In addition it also needs to work the other way around.
Originally posted by @jonasesr in #37 (comment)
Is there a way to set the currency label position with a property without set the currency property ?
something like:
<CurrencyInput
v-model="value"
currencyPosition="prefiy or sufix"
"/>
You can even observe it in the demo page. Locale does not matter.
Typing -1000 results in --1000
- focus out clears the input, nothing in the console.
Greetings and thank you for this sweet component.
I am having problems with cryptocurrencies. Some of them are handling well (BTC, ETH...), but test bitcoin (TBTC) is (obviously) throwing an error (Invalid currency codes at new NumberFormat).
Is there a way to manually bypass this validation?
thanks
Hello, I really love this plugin. But I got this warning, I currently use Vue version 2.6.1. Is there anyway we can prevent this warning. Thanks.
Hi. Is it possible to allow my input to be 10.05? At the moment when I typed to the point of "10." I can't put another "0". Thanks.
Hi there, great component!
I'm using the directive mode to build a wrapper component around yours, based on Element UI's input, so I can take advantage of Element's built in validator rules etc, and at the same time use a number in my VM.
It works fine, save for one detail: When I initialize the input/component with a value, e.g. 1500
, I'd like it to be displayed formatted, i.e. 1.500,00 €
(in the EUR/el locale case).
Tried by having currencyRef
emit blur,change etc, to no avail.
An idea would be to expose a formatValue
function, like you did with parseCurrency
, which could easily be used to convert incoming number to the proper format.
<template>
<div>
<el-input v-model="internalValue" v-currency="options" ref="currencyRef" class="currency-input"/>
</div>
</template>
<script>
export default {
props: ['value', 'currency'],
components: {},
data: function () {
return {
options: {
locale: 'el',
currency: this.currency,
distractionFree: true,
validateOnInput: false
},
internalValue: null
}
},
watch: {
value(newValue) {
this.internalValue = newValue
},
internalValue(newValue) {
this.$emit('input', this.$parseCurrency(newValue, this.options.locale, this.options.currency))
}
}
}
</script>
Hello. I tried to use v-currency as a directive (following the tutorial strictly, I just changed the input to v-text-field), but it didn't work (every time I entered a value, the same back to 0)
Would it be possible to add the ability to set a maximum and minimum accepted value? So that if a number is entered that puts the value over the maximum value or under the minimum value then the number is ignored and the current value is kept in the input.
For example, if the maximum value is 10
and the users enters 11
, the second 1
is ignored so that the input only shows the first 1
entered. The ignoring behavior is similar to how letters are ignored on input.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.