3

I'm having a look at Vue.js with a view to simplifying an application which is starting to get a bit too complex with jQuery. I want to utilise the data binding so that the state of an 'Order' object automatically enables or disables certain buttons (e.g., I want the submit button to be automatically disabled unless an order, containing items, exists). I have something which partly works, with this declaration:

 var content = new Vue({
    el: '#content',
    computed: {
        orderExists: function () {
            return (shopOrder != null && !isEmpty(shopOrder.items));
        }
    }
});

I use it in a button like this:

<button type="button" id="btnDisplay" v-bind:disabled="!orderExists">Show Selected</button>

On page load, the buttons using this technique are indeed enabled/disabled correctly. However, when I add items to the order object, thereby changing its state, I'm not seeing any update in the buttons' states - they should be being enabled.

I assume I'm misunderstanding something basic about how this works with Vue.js, as I've only spent a couple of hours with it, so any help would be appreciated.

0

2 Answers 2

2

Hmmm why not pass the property as reactive data?

You can do something like:

...
computed: {
        orderExists: function () {
            this.disabled = (shopOrder != null && !isEmpty(shopOrder.items));
        }
    }

Fiddle.

DP: the example is in Vue 2

Sign up to request clarification or add additional context in comments.

1 Comment

This won't work because if shopOrder is a plain JavaScript object that hasn't been made reactive by Vue, orderExists will never fire when it changes and disabled will never update. For more info see vuejs.org/guide/computed.html and read the "Computed Caching vs Methods" section. Also, there's no point in making this approach a computed because the value will always be undefined since it doesn't return a value.
2

The issue is that Vue has to manage your data objects in order to set them up in a way where it can observe the changes to them (i.e. be made reactive). This is done by specifying the data option to your Vue creation. Something like:

data: {
    shopOrder: null
}

Then update your code like this:

orderExists: function () {
    return (this.shopOrder != null && !isEmpty(this.shopOrder.items));
}

And of course at some point you need to set this.shopOrder to a valid order object.

4 Comments

I woke in the night with this very answer myself! I realised I had neglected to make it managed data. I've been working a bit with React.js in the last year and the same thing applies there, so I should have thought of that. I just have to read up about managing data now.
Still struggling with this, actually. I think my problem may be to with the way I'm updating my shopOrder property, possibly messing up the proxying. If I assign a new object to shopOrder , as opposed to updating its properties, should this still work? That is, if I do something like 'content.shopOrder=newOrder'? Failing that, is it permissible to add new properties to an existing managed data object?
It might help to see some code in a Fiddle. You have to make sure that the object is contained within the Vue itself using the data option and then later referencing it with this in the context of methods.
Slightly awkward to condense down the problem into a Fiddle. But in any case I actually now have this working as a result of giving up on the idea of trying to keep the Vue data in sync with the existing object I was using before. I've now switched everything to use the Vue data and dispensed with the old object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.