user10073186
user10073186

Reputation:

input box automatically changed to original value

When I change the input box, it will automatically change to original value by itself. It seems the reason is btnDisabled has been changed, because if I remove the line of this.btnDisabled = !this.btnDisabled; the input box will no more be automatically changed. I want to know why btnDisabled will affect the input box's value?

const vm = new Vue({
    el: '#app',
    data: {
        btnDisabled: false,
        total: 25,
    },
    created() {
        setInterval(() => {
            this.btnDisabled = !this.btnDisabled;
        }, 500);
    },
});
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>

<div id="app">
    <input type="text" v-bind:value="total">

    <button v-bind:disabled="btnDisabled">test</button>

</div>

Upvotes: 2

Views: 665

Answers (2)

The Alpha
The Alpha

Reputation: 146229

There is an answer by Steven B which might solve your problem but I would like to add a little bit about the problem identifying the cause. The problem is in the one-way-binding, what I mean is that, when you are using the following:

<input type="text" v-bind:value="total">

You are introducing a new separate state in DOM by allowing the user typing in the input. So, when the user types into the input, the data.total property is not being updating, it's still 25 but the DOM input has new value. In that case, when setInterval fires and data.btnDisabled is updated, the Application's state is changed and then VUE just force the component to be re-render to keep the data and the DOM in sync. I would prefer v-model instead of :value.

Upvotes: 1

Steven B.
Steven B.

Reputation: 9362

This is because Vue is rerendering the "component" and the value is still technically 25. You can use v-model or @input to update the data or you can use v-once to prevent Vue from rerendering the input text box.

const vm = new Vue({
    el: '#app',
    data: {
        btnDisabled: false,
        total: 25,
    },
    created() {
        setInterval(() => {
            this.btnDisabled = !this.btnDisabled;
        }, 500);
    },
});
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>

<div id="app">
    <input type="text" v-bind:value="total" v-once>

    <button v-bind:disabled="btnDisabled">test</button>

</div>

Upvotes: 2

Related Questions