<template>
<input
@input="formatValue"
type="text"
:value="formattedValue"
/>
</template>
<script type="text/javascript">
import {formatPhoneNumber} from '~/utils/string';
export default {
computed: {
formattedValue: function(){
return formatPhoneNumber(this.value)
},
},
methods: {
formatValue(e) {
this.$emit('input', formatPhoneNumber(e.target.value))
}
},
props: ['value']
}
</script>
As long as the formatPhoneNumber(value)
produces a different value, every thing works fine, but once the max length is reached (Since formatPhoneNumber('xx xx xx xx xx whatever') == 'xx xx xx xx xx'
), the emitted value is the same as the current store one.
It is totally fine, except that as a consequence, state is not mutated and component is not re-rendered, hence formattedValue()
is not called.
So I end up with xx xx xx xx xx
in the store, but the input displays xx xx xx xx xx whatever
as local input value varies from the store one.
How can I avoid this unexpected behavior? Moving formatPhoneNumber()
to the store would not solve my issue since it would still prevent mutation, and only using formatPhoneNumber()
in formattedValue()
would make me end up with an un-formatted value in the store which is not what I want either.
How come Vue's input
with dynamic value
set still manages a local state?
To achieve what you want (I think), you could change your formatValue method to
formatValue(e) {
this.$emit('input', e.target.value = formatPhoneNumber(e.target.value));
}
So that it sets the input to the formatted phone number value. One way or another you're going to be overriding what the input produces so you might as well do it on the input event.