Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Vue 3 debugging reference for reactivity issues, computed errors, watcher bugs, async failures, and SSR hydration problems.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
reference/v-model-number-modifier-behavior.md
1---2title: v-model.number Uses parseFloat Not valueAsNumber3impact: MEDIUM4impactDescription: .number modifier returns empty string for empty input and uses parseFloat, not native valueAsNumber5type: capability6tags: [vue3, v-model, forms, input, number, type-coercion, modifiers]7---89# v-model.number Uses parseFloat Not valueAsNumber1011**Impact: MEDIUM** - The `.number` modifier doesn't behave like the native `valueAsNumber` property. It returns an empty string (not NaN) for empty inputs, and uses `parseFloat()` which has different parsing rules. This can cause unexpected type issues in calculations and validations.1213Understanding these differences is crucial when working with numeric forms, especially for calculations, min/max validation, or when interfacing with APIs that expect strict number types.1415## Task Checklist1617- [ ] Expect empty string (not 0 or NaN) when input is cleared with `.number` modifier18- [ ] Handle the empty string case in your validation and calculations19- [ ] Remember `.number` uses parseFloat - "123abc" becomes 123, not NaN20- [ ] For strict numeric parsing, add custom validation2122**Key Differences:**2324| Scenario | `.number` modifier | Native `valueAsNumber` |25|----------|-------------------|----------------------|26| Empty input | `''` (empty string) | `NaN` |27| `"123"` | `123` | `123` |28| `"123.45"` | `123.45` | `123.45` |29| `"123abc"` | `123` | `NaN` |30| `"abc"` | `'abc'` (original string) | `NaN` |3132**Problem - Unexpected types:**33```html34<script setup>35import { ref, computed } from 'vue'3637const price = ref(0)38const quantity = ref(1)3940const total = computed(() => {41// PROBLEM: price might be '' (empty string) when input is cleared42return price.value * quantity.value // '' * 1 = 0, but typeof is still number43})4445function validatePrice() {46// PROBLEM: This check fails when input is empty47if (typeof price.value !== 'number') {48// Never enters here! '' is still treated as "processed"49}5051// PROBLEM: parseFloat("$100") returns NaN, but "100abc" returns 10052}53</script>5455<template>56<input v-model.number="price" type="number">57<!-- When user clears input, price.value becomes '' not 0 or NaN -->58</template>59```6061**Solution - Handle empty string explicitly:**62```html63<script setup>64import { ref, computed } from 'vue'6566const price = ref(0)67const quantity = ref(1)6869const total = computed(() => {70// CORRECT: Handle empty string case71const priceNum = price.value === '' ? 0 : price.value72return priceNum * quantity.value73})7475// Or use a wrapper computed for safer access76const safePrice = computed(() => {77if (price.value === '' || price.value === null) return 078return Number(price.value) || 079})80</script>8182<template>83<input v-model.number="price" type="number" min="0">84<p>Total: ${{ total.toFixed(2) }}</p>85</template>86```8788**Solution - Custom input handling for strict parsing:**89```html90<script setup>91import { ref } from 'vue'9293const price = ref(0)9495function handlePriceInput(event) {96const value = event.target.value9798// Strict parsing - only accept valid numbers99const parsed = parseFloat(value)100101if (value === '') {102price.value = 0 // Or null, depending on your needs103} else if (!isNaN(parsed) && isFinite(parsed)) {104// Additional check: ensure entire string is numeric105if (/^-?\d*\.?\d+$/.test(value.trim())) {106price.value = parsed107}108}109// Invalid input - keep previous value110}111</script>112113<template>114<!-- Manual binding for strict numeric control -->115<input116:value="price"117@input="handlePriceInput"118type="number"119>120</template>121```122123## Reference124- [Vue.js Form Input Bindings - .number](https://vuejs.org/guide/essentials/forms.html#number)125