vuetify
vuetify copied to clipboard
fix(VNumberInput): avoid showing NaN
Description
In order to avoid NaN
we need to decouple "text" model for VTextField and the "exposed" model representing value for VNumberInput's consumer. I don't see it any other way and this approach served me many years in my custom wrapper arount VTextField back in Vuetify 2, so I am pretty sure it's the only way forward.
Each time we sync between these two
- "text" model becomes valid number or an empty string – thanks to
typeof model.value === 'number' && !isNaN(...)
- "exposed" model becomes valid number – thanks to custom aggressive parsing in
extractNumber(...)
Note: there are many ways to break this implementation, so we will need a bunch of test cases as a safety net for future changes. I plan on introducing them in the following days.
fixes 19798
Markup:
<template>
<v-app theme="dark">
<v-container>
<v-card class="mx-auto pa-6 my-4" style="max-width: 1200px">
<v-row>
<v-col cols="4">
<small class="d-block mb-2">(clearable)</small>
<v-number-input v-model="emptyValue" clearable />
<code>value: {{ emptyValue }}</code>
</v-col>
<v-col cols="4">
<small class="d-block mb-2">(:step=".25")</small>
<v-number-input v-model="value1" :step=".25" />
<code>value: {{ value1 }}</code>
</v-col>
<v-col cols="4">
<small class="d-block mb-2">(:max="20" :min="-10")</small>
<v-number-input v-model="value2" :max="20" :min="-20" />
<div class="d-flex align-center justify-space-between">
<code>value: {{ value2 }}</code>
<div class="text-right">
<v-btn @click="value2 = 5.125">Set to 5.125</v-btn>
<v-btn @click="value2 = NaN">Set to NaN</v-btn>
</div>
</div>
</v-col>
</v-row>
</v-card>
</v-container>
</v-app>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const emptyValue = ref<number>(null)
const value1 = ref<number>(15)
const value2 = ref<number>(-10.25)
</script>