An error has occurred:
The property defaultValue cannot be read from undefined
This issue arises because the ref
is not immediately available:
It's important to note that refs are created as a result of the render function, so you cannot access them during the initial rendering phase - they simply do not exist yet! The $refs
object is also non-reactive, meaning it should not be used for data-binding in templates.
When you add the ref
to the template of the button
, it tries to use it too early.
To work around this issue, you can implement a simple conditional statement:
<button type="submit" :disabled="!$refs.input || $refs.input.defaultValue == $refs.input.value">Submit</button>
However, there's a catch.
The defaultValue
may not hold the expected value
When utilizing v-model
, the defaultValue
will always be an empty string (""
) because Vue initially renders the <input>
with an empty value.
If you wish to use a variable in the disabled button as intended, my suggestion is to make use of a mounted()
method to store the initial value and compare it within the button template rather than using defaultValue
.
A demonstration is provided below.
new Vue({
el: '#app',
data: {
name: 'Hello Vue.js!'
},
mounted() {
this.$refs.input.dataset.defVal = this.$refs.input.value;
}
})
<script src="https://unpkg.com/vue"></script>
<div id="app">
<p>{{ name }}</p>
<input type="text" v-model="name" ref="input" />
<button type="submit" :disabled="!$refs.input || $refs.input.dataset.defVal == $refs.input.value">Submit</button>
</div>
Another Option: Embrace Vue's Approach Completely
If possible, fully leverage Vue's reactive nature rather than manipulating the DOM directly.
The solution involves creating another variable set in the mounted()
method:
new Vue({
el: '#app',
data: {
name: 'Hello Vue.js!',
defaultName: null
},
mounted() {
this.defaultName = this.name;
}
})
<script src="https://unpkg.com/vue"></script>
<div id="app">
<p>{{ name }}</p>
<input type="text" v-model="name"/>
<button type="submit" :disabled="name == defaultName">Submit</button>
</div>
Alternatively, if both name
and defaultName
can be set to the same initial value, the mounted()
logic mentioned above would not be required.