Input field is not reactive updating as expected
Vue version
3.3.0-alpha.12
Link to minimal reproduction
Steps to reproduce
Works with different maximum numbers:
Default Example Case with max value 100
Type a number into the input field
If the number is starting with a "1" and you type afterwards 2 digits like "04". Then the displayed value in the Input field is updated to be the max value 100 which is expected.
If you add a 4th digit like 1000 suddenly the computed getter is not called anymore. The emitted value by the NumberInput Component is still correct. But the displayed number in the input is wrong.
For all numbers between 100 and 199 it works as expected If you habe the number 100 and alter the first digit than even 200 it doesn't work properly If you type 200 into an empty input it works
Using the add and subtract buttons always works
Case max 1000
Behaves similar. Only works as expected for number from 1000 1999
What is expected?
All numbers that are entered above the max value should be "clamped" to the max value and should be also displayed like that in the input field
What is actually happening?
Number which are entered above the max value are getting correct clamped in the "ref" variable. But the input field is not updating correctly.
System Info
System:
OS: macOS 13.3.1
CPU: (8) arm64 Apple M1
Memory: 160.80 MB / 16.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 16.20.0 - /opt/homebrew/opt/node@16/bin/node
Yarn: 1.22.19 - /opt/homebrew/bin/yarn
npm: 8.19.4 - /opt/homebrew/opt/node@16/bin/npm
Browsers:
Chrome: 112.0.5615.121
Firefox: 112.0.1
Safari: 16.4
npmPackages:
vue: ^3.2.37 => 3.2.47 // but also in 3.3.0-alpha.12 of the SFC Playground
Any additional comments?
No response
This is kinda expected because after 100 has been set for the first time, for any new input above 100,
- the NumberInput emits the same value each time: 100.
- So the parent never needs to re-render,
- and as result never passes a new
modelValue
value to the child, - so the NumberValue never re-renders and
- without a re-render, the inout value is never updated back to 100.
the v-model
on the input syncs the input to the local ref. if that ref never changes, Vue sees no need to update the input.
clamping the value in this way does not work with v-model, because it wants to keep the values in sync, but you break that synchronisation.
You would need to use a template ref and manually re-set the input value whenever the clamp function resets a value to the max/min.
const inputField = ref()
// create clamp function
function clamp(value: number, min: number, max: number): number {
const newValue = Math.min(Math.max(value, min), max);
if (newValue !== value) {
inputField.value.value = newValue
}
return newValue
}