Формат чисел Маска теряет дробные цифры при маскировке десятичных дробей

Я пытаюсь добавить форматированное поле в свое приложение vue, используя маску. До сих пор все работает нормально, если мое значение не содержит цифр фракции (например, 26767).

Но если я получу значение с фракцией типа 26717.01, я получу результат 2.671.701 (я ожидаю 26.717,01)

Может ли кто-нибудь указать мне правильное направление?

<script setup lang = "ts">
import { vMaska } from "maska/vue";


const emit = defineEmits([ 'update:modelValue']);

let props = defineProps({
  amount: {
    type: Number
  },
})

const options = {
  number:{
    fraction: 2,
    locale: 'de-DE'
  },
};

</script>
<script lang = "ts">
import {defineComponent} from "vue";

export default defineComponent({
  name: 'AmountField',
});

</script>

<template>
  <v-text-field
    variant = "outlined"
    :clearable=false
    density = "compact"
    auto-grow
    rows = "1"
    :model-value = "props.amount"
    v-maska = "options"
    v-bind = "$attrs"
    @maska = "(event) => {console.info(event.detail.unmasked); emit('update:modelValue',Number(event?.detail?.unmasked))}"
  />
</template>

<style scoped>

</style>

мои тестовые примеры выглядят так:

import AmountField from "@/components/elements/AmountField.vue";

describe('xxxx', (): void => {

  it('no fraction', () => {

    cy.mount(AmountField, {
      propsData: {
        amount: 26717,
        editable: true,
        id: "amountField"
      }
    } as any).then(({wrapper, component}) =>
    {
      cy.get("#amountField").find('input').should('have.value', '26.717').should('not.be.disabled')
      cy.get("#amountField").find('input').type('{selectAll}1234,56').then(() => {
        expect((wrapper).emitted('update:modelValue')).to.have.length;
        expect((wrapper).emitted('update:modelValue')[7][0]).to.equal(1234.56)
      })

    });
  })

  it('with fraction', () => {

    cy.mount(AmountField, {
      propsData: {
        betrag: 26717.01,
        editable: true,
        disabled: true,
        id: "amountField"
      }
    } as any);
    cy.get("#amountField").find('input').should('have.value', '26.717,01')
  })

})
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это проблема в Maska (v3.0) с числовым вводом и форматом, который использует точку в качестве разделителя группировки (например, немецкий 1.000.000,99). Даже если ввод не замаскирован, Маска начинает с удаления разделителя группировки. Таким образом, если входные данные представляют собой число с плавающей запятой, а разделителем группировки является точка, десятичная точка будет удалена. 26717.01 становится 2671701, который форматируется как 2.671.701.

Я предполагаю, что это непреднамеренное поведение. В качестве обходного пути вы можете начать с уже отформатированного значения:

<template>

  <v-text-field
    v-model = "maskedValue"
    v-maska:amount.unmasked = "options"
  />

</template>
<script setup>

const amount = ref(26717.01)
const options = {...}
const preformattedValue = new Intl.NumberFormat(options.number.locale).format(amount.value)
const maskedValue = ref(preformattedValue)

</script>

Если amount можно изменить снаружи, вам, вероятно, придется использовать наблюдатель для обновления форматированного значения.

const { createApp, ref } = Vue;
const { createVuetify } = Vuetify
const vuetify = createVuetify()
const app = {
  directives: {maska: window.Maska.vMaska},
  template: `
      <v-app>
        <v-main>
          <v-container>

            <v-text-field
              v-model = "maskedValue"
              v-maska:amount.unmasked = "options"
            />
            
            <pre>amount: {{amount}}</pre>
          
          </v-container>
        </v-main>
      </v-app>
  `,
  setup(){
    const options = {
        number: {
          fraction: 2,
          locale: 'de',
        },
        reversed: true,
      }
    const formatter = new Intl.NumberFormat(options.number.locale)
    const amount = ref(26717.01)

    return {
      amount,
      maskedValue: ref(formatter.format(amount.value)),
      options,
    }
  }

}
const a = createApp(app).use(vuetify).mount('#app')
<link rel = "stylesheet" type = "text/css" href = "https://cdn.jsdelivr.net/npm/vuetify@3/dist/vuetify.min.css" />
<link href = "https://cdn.jsdelivr.net/npm/@mdi/font/css/materialdesignicons.min.css" rel = "stylesheet">
<div id = "app"></div>
<script src = "https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<script src = "https://cdn.jsdelivr.net/npm/vuetify@3/dist/vuetify.min.js"></script>
<script src = "https://unpkg.com/[email protected]/dist/cdn/vue.js"></script>

Другие вопросы по теме