Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Strict precision for VNumberInput #19898

Open
J-Sek opened this issue May 27, 2024 · 1 comment · May be fixed by #20252
Open

[Feature Request] Strict precision for VNumberInput #19898

J-Sek opened this issue May 27, 2024 · 1 comment · May be fixed by #20252
Labels

Comments

@J-Sek
Copy link
Contributor

J-Sek commented May 27, 2024

Problem to solve

In my large web app I have multiple forms with many different use cases for number inputs. When I want user to put a value in USD it should display nicely using expected formatting and enforce up to 2 decimal digits. Having "$" prefix is OK, but actually formatting and enforcing precision is a level-up in terms of UX.

Playground

Proposed solution

  • new prop precision
  • typing more digits should be allowed, but should trigger validation message
  • blur event should cut off unnecessary characters (it would be great to never emit them to the parent component)

Simplified implementation:

// <v-text-field v-model='internalValue' :rules='rules' @blur='onBlur' />

const internalValue = ref('');
const props = defineProps<{
  grouping?: boolean;
  precision?: number | null;
}>();
const enforcePrecision = computed(() => props.precision != null && props.precision > 0 && Number.isInteger(props.precision));

const rules = computed(() => [
  (v: number | null) => !v || !enforcePrecision.value || (String(v).split('.')[1] ?? '').length <= props.precision || `Expected up to ${props.precision} decimal places`,
]);

async function onBlur(event: Event) {
  if (!isEmpty(internalValue)) {
    emit(formatForEmit(internalValue));
  }
);

I think implementation would require additional props for grouping character and decimal separator.

propsFactory({
  groupingSeparator: { type: String, default: ',' },
  decimalSeparator: { type: String, default: '.' },
  // ...
});
function formatForField(v: string) {
  // add grouping separator if props.grouping === true
  // add decimal separator if props.precision > 0 or undefined
  // cut decimal part if props.precision > 0
}
function formatForEmit(v: string) {
  return parseNumber(formatForField(v));
}
function parseNumber(v: string) {
  // remove everything except first occurrence of decimal separator and `-` sign before passing text to `parseFloat`
}

Related to:

@J-Sek
Copy link
Contributor Author

J-Sek commented Jun 1, 2024

We could take some inspiration from PrimeVue's InputNumber. However their API binds itself strongly to Intl.NumberFormat`. We could deliver better DX with:

  • grouping: Boolean (default: false)
  • precision: Number (default: 0) – to handle both min and max as I don't see the reason for split
  • formatterOptions: Intl.NumberFormatOptions – total flexibility without polluting component's API

Edit: I will not continue subject of grouping/formatting in this issue in order to keep it focused on precision and hopefully get it done faster.

@J-Sek J-Sek changed the title [Feature Request] Strict precision and grouping for VNumberInput [Feature Request] Strict precision for VNumberInput Jul 30, 2024
@J-Sek J-Sek linked a pull request Jul 30, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants