Giter VIP home page Giter VIP logo

intl-number-input's People

Contributors

dm4t2 avatar github-actions[bot] avatar ragulka avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

intl-number-input's Issues

Min value range not working with percent

I'm trying to use the min range value with the format percent, but the element always returns the max value.
As you can see in the following screenshot in your playground, I inserted a minimum value of 10% and a maximum value of 50%, but the Number value will always be 50%.

image

Update: if the min value is 0 it works correctly

Precision without specifying number of digits before and after decimal

Thank you for this great library!

It looks like you support 16 digit precision, but the number of digits before and after the decimal needs to be specified ahead of time. Is there a way to support 16 digit precision but allow the decimal to be placed anywhere? For example, can all of these be supported at the same time?

1,234,567,890,123,456
123,456,789,012,345.6
12,345,678,901,234.56
1,234,567,890,123.456
123,456,789,012.3456
12,345,678,901.23456
1,234,567,890.123456

Initializing with unformatted number / usage as a Vue custom component

I'm trying to create a custom NumericInput component in Vue using this package and hit a snag, because it expects that the input element holds the formatted number on initialization. However, in my case, the number is supplied by the backend unformatted, as a regular number.

This is not a problem when using a locale that uses period . as the decimal separator, however it becomes an issue when the locale uses comma as the decimal separator: after I focus on the field and try to type into it, the period is removed and something like 123.45 becomes 12345 which is obviously not what I want.

Looks like the constructor tries to parse the input element's value here and there's no way to work around it.

Here's what I have so far:

<!-- NumericInput.vue -->
<template>
    <input ref="inputRef" :value="modelValue" />
</template>

<script setup>
import { defineProps, defineEmits, ref, onMounted } from 'vue'
import { NumberInput } from 'intl-number-input'

const props = defineProps({
    modelValue: {
        type: Number,
        default: null,
    },
})

const emit = defineEmits(['update:modelValue', 'change'])
const inputRef = ref(null)

onMounted(() => {
    if (inputRef.value) {
        const numberInput = new NumberInput({
            el: inputRef.value,
            options: {
                locale: 'et',
                formatStyle: 'decimal',
                precision: 2,
                hideNegligibleDecimalDigitsOnFocus: false,
            },
            onInput: value => emit('update:modelValue', value.number),
            onChange: value => emit('change', value.number),
        })
    }
})
</script>

<!-- usage -->
<NumericInput v-model="123.45" />

I guess I could use a computed formatted number for the element value instead, which would allow me to pass in an unformatted number & format it on component initialization. This would initialize the NumberInput instance correctly, at least.

However, there is another issue: I want to emit the raw number value on input & change. This causes a loop where the emitted value.number causes a recalculation of the computed formattedValue, which causes the caret to jump around in the input as I type.

Perhaps there's an easy way to fix this so forgive me if I'm missing something.

Add ability to destroy/unbind/teardown

Hi! Thanks for super work - so nice to se WebAPIs utilized in this way!

Situation:
I'm working in a webpage, where elements appear and disappear based on state.
Currently intl-number-input only binds events, but it has no destroy/unbind/teardown method, meaning there is no way to do garbage collection/free up memory.

Solution:
Add a .destroy method removing the instance and all listeners. Example API:

const numberInput = new NumberInput({
  el: document.querySelector('input'),
  options: {
    // see API reference
  }
})

// set initial value
numberInput.setValue(1234)

// Remove listeners and other references so element can be garbage collected
numberInput.destroy()

hidePrefixOrSuffixOnFocus does not work as expected

Given the currency, unit or percent style, I would expect hidePrefixOrSuffixOnFocus: true to hide the prefix or suffix, well.. when the input is focused ๐Ÿ˜„. However, in my testing, the behavior is different:

  • Using currency or unit, the prefix/suffix is hidden only once I start typing. I would expect it to be hidden as soon as the input gains focus.
  • Using percent, the prefix/suffix is always hidden, whether the input is focused or not. I would expect it to be visible when not focused and only disappear when focused.

Note that hidePrefixOrSuffixOnFocus: false seems to work as expected.

Getting SyntaxError: Unexpected token 'export' in Vite build

Hi,

I'm using intl-number-input in a SvelteKit app and I'm getting this error:

(node:71606) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
/Users/andreas/Projects/summerator/node_modules/intl-number-input/dist/index.esm.js:589
export { CurrencyDisplay, NumberFormatStyle, NumberInput, UnitDisplay };
^^^^^^

SyntaxError: Unexpected token 'export'
    at Object.compileFunction (node:vm:352:18)
    at wrapSafe (node:internal/modules/cjs/loader:1031:15)
    at Module._compile (node:internal/modules/cjs/loader:1065:27)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:190:29)
    at ModuleJob.run (node:internal/modules/esm/module_job:185:25)
    at async Promise.all (index 0)
    at async ESMLoader.import (node:internal/modules/esm/loader:281:24)

SvelteKit apps are built with Vite and this is not an uncommon issue. I'm not deep enough into Vite to fully understand what's going wrong. All I could figure out is that it's to do with loading of ESM modules.

The error can be avoided by adding "type": "module" in node_modules/intl-number-format/package.json which isn't really a fix but might point to the source of the problem.

The App is quite minimal and if you care to check it out and help me fix it, I'd very much appreciate it :)

https://github.com/juni0r/summerator/tree/intl-number-input

npm install
npm run test

or

npm run build
npm run preview

Thanks!

Allow providing min & max precision

Thanks for fixing decimal format issues (#1)! I wanted to use this for a price input that allows a flexible number of decimals between a defined min and max precision. The idea is the same as the minimumFractionDigits and maximumFractionDigits options of the Intl API. I realize the same issue has been raised before in dm4t2/vue-currency-input#261 - but I hope there's a way to add support to it in this package.

As mentioned in the above issue, it's extremely helpful in cases where a price or number input needs to have at least 2 decimal places, but may support more for higher precision (say 5), if necessary.

By looking at the relevant source code it doesn't look like the hideNegligibleDecimalDigitsOnFocus option would conflict with a precision range, as it only uses the maximumFractionDigits of the number format.

Could this be implemented or am I missing something? I'm happy to try and send a PR - I'm just not too confident with my TypeScript foo ๐Ÿ˜…

Decimal symbol detection is broken for decimal and percent styles

I understand this is a very-very early release of this package, but I wanted to try it out nonetheless, as it would be immensely helpful for a project I'm working on.

I noticed that it's currently impossible to use the decimal style with... decimals! ๐Ÿ˜… As I ventured into the code, I also noticed that there is no type declaration for the percent style, which is supported by Intl.NumberFormat. Regardless of the missing type, I tried setting the type to percent and noticed that it does not work as expected, either.

Issue description and reproduction

Given the following, it's impossible to enter any decimals in the input:

new NumberInput({
    el: inputElementFromSomeWhere,
    options: {
        formatStyle: NumberFormatStyle.Decimal,
        precision: 4,
    },
})

Here's a bare-bones reproduction of the issue: https://codepen.io/ragulka/pen/NWgmqaE

  1. Notice that the input value is 123456.789 initially
  2. Click on the input - the value is formatted, but the decimal point is lost (value is converted to an integer)
  3. Try entering an amount with a decimal place - when hitting comma or period on the keyboard, nothing happens

I would expect to be able to enter at least 4 decimal places, since I've set precision: 4.

Tracking down the cause

As I tried to debug this, I noticed that the NumberFormat class tries to detect the decimal symbol and when it cannot find one, it'll set minimumFractionDigits and maximumFractionDigits to 0, regardless of the precision option.

The culprit seem to be these lines. In order to detect the decimal symbol (as well as other symbols, like the negative, etc), a number is formatted with the given style. Then, it tries to see if there are any decimal places by checking if there are any zeroes in the formatted number. Since there are no zeroes in the input number (123456), having zeroes would mean there's a decimal point right where the first zero is inserted.

The logic above assumes that there are decimal places (minimumFractionDigits > 0) in the default format for the given style. This is only true for currency, though. While decimal places are perfectly valid for decimals and percentages, decimals and percentages do not have a minimum amount of decimals by default. Formatting the number 123456 as decimal with will result in 123,456 - not 123,456.00. Also formatting 1 as percent will yield 100% which will throw off the decimal detection completely.

In conclusion, it seems the decimal symbol detection is flawed - while it works for currencies (by lucky chance), it's not really suitable for other numbers.

Proposed change

There are more reliable ways to get the decimal and thousand separators.

If IE11 is not a concern (Vue 3 does not support it), I'd suggest simply using NumberFormat#formatToParts.

var formatter = new Intl.NumberFormat('de-DE', { style: 'decimal' });

formatter.formatToParts(123456.789);

// return value:
[
  { type: "integer",  value: "123"   },
  { type: "group",    value: "."   },
  { type: "integer",  value: "456" },
  { type: "decimal",  value: ","   },
  { type: "fraction", value: "789"  }
]

However, if IE11 is a thing, it's possible to use the other solution in the linked SO answer.

In any case, it's imperative to use a number with existing decimal places as input for the formatter, regardless of the chosen solution.

EDIT: I have a proof-of-concept implementation in my fork here - it's raw, but it shows the concept and it works as expected as far as I tried.

Why does component rerender break this?

I have no idea what could be causing this, I have fought with this for hours and I'm losing my mind.

At the top of my component you will notice:

@blur="onBlur"
:valid="meta.valid"
:touched="meta.touched"
:error="errorMessage"

The 3 props come from veeValidate, and the onBlur calls a vee method which updates those props (the meta object)

Whenever this gets updated, the entire component breaks and resets the input, presumably because the component is rerendering.

I made a sandbox. you will notice it adds $5000 automatically after 1 second. once that occurs, click in the box and immediately click out of it without typing and you will see the entire input clear.

https://codesandbox.io/s/jolly-cloud-4yysns?file=/src/components/AppInput.vue

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.