3.22.2 • Published 2 years ago

@lanz1/v-money3 v3.22.2

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

workflow TypeScript

Money Mask for Vue 3

View Demo

The Mask Money

Disclaimer

The old v-money library seems to be abandoned! Since I use it in many projects and part of then will be upgraded to Vue3, I needed it to work after the upgrades.

Feel free to open an issue or post a pull request!

Features

  • Arbitrary Precision with BigInt
  • Lightweight (<4KB gzipped)
  • Dependency free
  • Mobile support
  • Component or Directive flavors
  • Accept copy/paste
  • Editable
  • Min / Max Limits

Arbitrary precision

Arbitrary precision is only supported with v-model. It expects to receive a string representation of a number. '12345.67'

Some break changes where introduced in this release. Let's follow a train of thought:
If your precision is set to 2 and you set a default model value of '55', it will be interpreted as '0.55'. To instruct the correct format on setup you need to pass in '55.00' when using v-model. The same is true for '5.5'. It will be interpreted as '0.55'. Another example: '55.5' => '5.55'. Arbitrary precision is supported by using string and BigInt with v-model.

For the majority of users, it will make sense to use float numbers and stay within the boundaries of Number. If you fit this instance, you need to use v-model with the number modifier, or v-model.number. But than, you are stuck with numbers smaller than 2^53 - 1 or 9007199254740991 or 9,007,199,254,740,991. Little more than nine quadrilion... See MAX_SAFE_INTEGER.

For those who are using v-model.number, integers and floats are compleatly understood.
Let's follow another train of thought:
If your precision is set to 2 and you set a default model value of 55, it will be interpreted as 55.00. The same is true for 5.5. It will be interpreted as 5.50. Another example: 55.5 => 55.50.

More Examples

Usage

Installation

npm i v-money3 --save

Register Globally (view codesandbox)

import { createApp } from "vue";
import money from 'v-money3'

const app = createApp({/* options */})

// register directive v-money3 and component <money3>
app.use(money)

Only Global Component (view codesandbox)

import { createApp } from "vue";
import { Money3Component } from 'v-money3'

const app = createApp({/* options */})

// register component <money3>
app.component("money3", Money3Component)

Only Global Directive (view codesandbox)

import { createApp } from "vue";
import { Money3Directive } from 'v-money3'

const app = createApp({/* options */})

// register directive v-money3
app.directive('money3', Money3Directive)

Use as component (view codesandbox)

<template>
  <money3 v-model="amount" v-bind="config"></money3> {{ amount }}
</template>

<script>
  import { Money3Component } from 'v-money3'

  export default {
    components: { money3: Money3Component },
    data () {
      return {
        amount: '12345.67',
        config: {
          masked: false,
          prefix: '',
          suffix: '',
          thousands: ',',
          decimal: '.',
          precision: 2,
          disableNegative: false,
          disabled: false,
          min: null,
          max: null,
          allowBlank: false,
          minimumNumberOfCharacters: 0,
        }
      }
    }
  }
</script>

Component v-model number modifier (view codesandbox)

v-model will always return a string. If the masked property is set to true it will be formatted, otherwise it will be a fixed string representation of a float number. If you need your model to be a float number use the number modifier. Ex.: v-model.number="amount"

  • v-model="amount" will return a fixed string with typeof string. Ex.: "123456.78"
  • v-model.number="amount" will return a float number with typeof number. Ex.: 123456.78
<template>
  <money3 v-model.number="amount" v-bind="config"></money3>
</template>

<script>
  import { Money3Component } from 'v-money3'

  export default {
    components: { money3: Money3Component },
    data () {
      return {
        amount: 12345.67,
        config: { ... }
      }
    }
  }
</script>

Use as directive (view codesandbox)

Must use v-model.lazy to bind works properly.

<template>
  <input v-model.lazy="amount" v-money3="config" />
</template>

<script>
  import { Money3Directive } from 'v-money3'

  export default {
    data () {
      return {
        amount: '12345.67',
        config: {
          prefix: '',
          suffix: '',
          thousands: ',',
          decimal: '.',
          precision: 2,
          disableNegative: false,
          disabled: false,
          min: null,
          max: null,
          allowBlank: false,
          minimumNumberOfCharacters: 0,
        }
      }
    },
    directives: { money3: Money3Directive }
  }
</script>

By default directives work with v-model. It is not possible to use v-model.number on directives, so, if you need to work with floats/integers on directives you need to configure the number modifier manually.

Using config:

modelModifiers: {
  number: true,
}

If you bind it directly you are just fine too:

<input :model-modifiers="{ number: true }" v-model.lazy="amount" v-money3="config" />

Properties

propertyRequiredTypeDefaultDescription
precisiontrueNumber2How many decimal places
decimalfalseString"."Decimal separator
thousandsfalseString","Thousands separator
prefixfalseString""Currency symbol followed by a Space, like "R$ "
suffixfalseString""Percentage for example: " %"
maskedfalseBooleanfalseIf the component output should include the mask or not
disable-negativefalseBooleanfalseComponent does not allow negative values
disabledfalseBooleanfalseDisable the inner input tag
minfalseNumbernullThe min value allowed
maxfalseNumbernullThe max value allowed
allow-blankfalseBooleanfalseIf the field can start blank and be cleared out by user
minimum-number-of-charactersfalseNumber0The minimum number of characters that the mask should show
should-roundfalseBooleantrueShould default values be rounded or sliced

Restricted Characters

Numbers 0-9 and the following characters...

  • +
  • -

...are restricted on following properties:

  • decimal
  • thousands
  • prefix
  • suffix

Restricted inputs will be filter out of the final mask. A console warn with more information will be shown!

Don't want to use a package manager?

Use it directly in the browser!

<script src="https://unpkg.com/v-money3@3.22.1/dist/v-money3.umd.js"></script>

Take a look at issue #15 and also this codesandbox working example.

Use the internal mask functions

import { format, unformat } from 'v-money3';

const config = {
    debug: false,
    masked: false,
    prefix: '',
    suffix: '',
    thousands: ',',
    decimal: '.',
    precision: 2,
    disableNegative: false,
    disabled: false,
    min: null,
    max: null,
    allowBlank: false,
    minimumNumberOfCharacters: 0,
    modelModifiers: {
        number: false,
    },
}

const formatted = format(12345.67, config);
console.log(formatted);
// output string: 'R$ 12.345,67 #'

const unformatted = unformat(formatted, config);
console.log(unformatted);
// output fixed string: '12345.67'

/* ----------------- or ----------------- */

config.modelModifiers = { number: true };

const unformatted = unformat(formatted, config);
console.log(unformatted);
// output float number: 12345.67

References

ababacorn-globalsacornacorn-jsxagent-baseacorn-walkansi-escapesajvansi-regexansi-stylesargparseanymatcharr-diffarr-unionarr-flattenarray-includesarray-uniquearray.prototype.flatarray-unionassign-symbolsasynckitatobbabel-plugin-istanbulaxiosbabel-plugin-dynamic-import-nodebabel-plugin-jest-hoistbabel-plugin-polyfill-regeneratorbabel-plugin-polyfill-corejs2babel-preset-current-node-syntaxbabel-plugin-polyfill-corejs3babel-preset-jestbase64-jsbalanced-matchblboolbasebrace-expansionbracesbrowser-process-hrtimebserbrowserslistbasebs-loggercache-basebufferbuffer-crc32buffer-fromcall-bindcapture-exitcamelcasecaniuse-litecallsiteschownrchalkchar-regexci-infoclass-utilscocjs-module-lexercliuiclone-deepcolor-convertcolor-namecollection-visitcollect-v8-coveragecombined-streamconcat-mapcomponent-emittercommanderconfusing-browser-globalsconvert-source-mapcopy-descriptorcore-js-compatcross-fetchcsscross-spawncssesccssstylecssomcwdcsstypedata-urlsdebugdecamelizede-indentdecode-uri-componentdecimal.jsdeep-isdeepmergedelayed-streamdefine-propertiesdefine-propertydetect-newlinediff-sequencesdir-globdoctrinedomexceptiondevtools-protocolemoji-regexelectron-to-chromiumemitteryend-of-streamerror-exes-shim-unscopableses-abstractesbuildes-to-primitiveescape-string-regexpescaladeeslint-import-resolver-nodeeslint-module-utilseslint-scopeescodegenesbuild-darwin-arm64eslint-utilseslint-visitor-keysespreeesprimaestraverseesqueryesrecurseestree-walkerexecaesutilsexec-shexpand-bracketsexitexpand-tildeextglobexpect-puppeteerextract-zipextract-from-cssexpectextend-shallowfast-levenshteinfast-deep-equalfast-json-stable-stringifyfast-globfastqfill-rangefd-slicerfb-watchmanfile-entry-cachefind-upfind-processfind-file-upfind-pkgfor-infor-ownflat-cachefragment-cachefollow-redirectsflattedfs-exists-syncfs-constantsfseventsfs.realpathform-datafunction.prototype.namefunction-bindfunctions-have-namesgensyncget-caller-fileget-intrinsicget-streamglob-parentget-symbol-descriptionglobglobal-prefixget-valueglobal-modulesglobbygrowlygrapheme-splitterglobalsgraceful-fshashas-flaghas-bigintshas-property-descriptorshas-valuehas-symbolshas-valueshehas-tostringtaghosted-git-infohomedir-polyfillhtml-encoding-snifferhtml-escaperhttps-proxy-agenthttp-proxy-agenthuman-signalsiconv-liteieee754ignoreimport-freshimurmurhashinflightimport-localinheritsiniinternal-slotis-arrayishis-bigintis-accessor-descriptoris-bufferis-ciis-boolean-objectis-callableis-data-descriptoris-core-moduleis-descriptoris-extendableis-date-objectis-dockeris-fullwidth-code-pointis-generator-fnis-globis-extglobis-negative-zerois-plain-objectis-number-objectis-numberis-potential-custom-element-nameis-regexis-shared-array-bufferis-symbolis-stringget-package-typeis-typedarrayis-windowsisobjectisarrayis-streamis-weakrefis-wslisexeistanbul-lib-coverageistanbul-lib-reportistanbul-lib-source-mapsistanbul-reportsjest-changed-filesjest-cliistanbul-lib-instrumentjest-configjest-diffjest-dev-serverjest-docblockjest-environment-jsdomjest-eachjest-environment-nodejest-get-typejest-leak-detectorjest-environment-puppeteerjest-haste-mapjest-matcher-utilsjest-mockjest-pnp-resolverjest-message-utiljest-regex-utiljest-resolvejest-jasmine2jest-resolve-dependenciesjest-runnerjest-runtimejest-utiljest-serializerjs-tokensjest-validatejest-watcherjoijs-sdsljs-yamljest-snapshotjsdomjsescjson-stable-stringify-without-jsonifyjson-schema-traversejson5kind-oflazy-cachelevenjson-parse-even-better-errorskleurlodash.debouncelevnlocate-pathlines-and-columnslodash.mergelodashlru-cachemagic-stringmake-dirmake-errormap-cachemakeerrormap-visitmerge2merge-streamjest-workermerge-deepmime-dbmixin-deepmime-typesminimatchmixin-objectminimistmsmicromatchmimic-fnnanoidmkdirp-classicnanomatchmkdirpnatural-comparenice-trynode-int64node-releasesnormalize-package-datanormalize-pathnpm-run-pathnode-bin-setupnode-notifiernode-fetchobject-copynwsapiobject-visitnth-checkobject-inspectobject-keysobject.assignonceobject.valuesobject.entriesobject.pickoptionatorp-finallyp-tryp-limitonetimep-each-seriesparse-passwdpascalcaseos-homedirparse-jsonparent-moduleparse5path-existspath-is-absolutep-locatepath-parsepath-keypath-typependpiratesposix-character-classespicomatchpicocolorspkg-dirprelude-lspostcss-selector-parserpretty-formatprogresspromptspslpumppunycodeproxy-from-envpostcssquerystringifyqueue-microtaskpuppeteerreact-isread-pkgread-pkg-upregenerate-unicode-propertiesreadable-streamregenerator-transformregenerator-runtimeregex-notregexpu-coreregenerateregexp.prototype.flagsregexppregjsgenrepeat-stringregjsparserrequire-directoryremove-trailing-separatorresolve-dirrepeat-elementrequires-portresolve-fromrequire-main-filenameresolveresolve-cwdretresolve-urlrsvpreusifyrollupsafe-buffersafe-regexrun-parallelsafer-bufferrxjssafe-regex-testset-blockingrimrafsaxesset-valueshallow-cloneshellwordssanesemvershebang-regexside-channelsnapdragonsisteransishebang-commandsnapdragon-nodesignal-exitslashsnapdragon-utilsource-mapsource-map-jssource-map-supportsource-map-resolvesourcemap-codecsplit-stringsource-map-urlspdx-correctspawndspdx-license-idsstatic-extendspdx-expression-parsesprintf-jsspdx-exceptionsstring-lengthstring-widthstack-utilsstring.prototype.trimstartstring.prototype.trimendstrip-ansistrip-bomstrip-eofstring_decoderstrip-final-newlinestrip-json-commentssupports-hyperlinkssupports-colorsupports-preserve-symlinks-flagtar-fsterminal-linktext-tabletest-excludethroatthroughsymbol-treeto-object-pathtar-streamtmplto-regex-rangeto-fast-propertiesto-regextsconfigtr46tough-cookietree-killtsconfig-pathstype-checktslibtypedarray-to-buffertype-detecttsutilsunbox-primitiveunicode-canonical-property-names-ecmascriptunicode-match-property-ecmascriptunicode-property-aliases-ecmascriptunset-valueunicode-match-property-value-ecmascripttype-festunion-valuetypescriptunbzip2-streamuri-jsuniversalifyutil-deprecateurixuseurl-parseupdate-browserslist-dbv8-to-istanbuluuidvue-template-compilerw3c-xmlserializerw3c-hr-timewhatwg-mimetypewalkerwait-onvalidate-npm-package-licensewhatwg-encodingvue-eslint-parserwebidl-conversionswhichword-wrapwhich-modulewhatwg-urlwrite-file-atomicwrappyxmlcharsy18nwsxml-name-validatorwhich-boxed-primitiveyauzlwrap-ansiyargs-parseryallistyargsyocto-queue
3.22.2

2 years ago