0

This appears in my browser console:

[Vue warn]: Error when evaluating expression "permissions.edit": TypeError: Cannot read property 'edit' of undefined (found in component: <heading>)

Related code:

{{ permissions | json }}
<a class="button" v-on:click="toggleEditMode" v-if="permissions.edit">{{ editMode ? 'Save' : 'Edit' }}</a>

Results in:

Screenshot

Permissions is obviously not undefined. What's going on? To make matters more confusing, if I pass a literal object to the component (:permissions="{edit: true}"), the warning goes away, but the json output from {{ permissions | json }} looks exactly the same.

3
  • 1
    The issue seems to be that you somehow added the edit property in a way that Vue did not notice it. (the json filter doesn't care for reactivity, so it does not matter there ) When and how are you creating / filling the permissions object? Do you change it somewhere, in a ready() hook or something? Did you define the permissions object in the components data with the edit property already in place? These are relevant infos we need. Commented Apr 11, 2016 at 20:09
  • It's a server response from vue-resource, created in the created() method of my ViewModel. It's assigned to the ViewModel with this.$set, and passed as a prop in my template. Commented Apr 11, 2016 at 20:44
  • There we go. The APi call with vue-resource is async, meaning Vue does not wait for it to finish, but instead continues to compile the template, which happens much faster than the API call. so when Vue evaluates permissions.edit, it has not yet been set, as the API call is still going on in the background. As soon as that call has finished, permissions gets set properly and your template works as expectd. Commented Apr 11, 2016 at 22:08

2 Answers 2

2

As discussed in the comments to your post, it's due to the async API call yo do in created() to get the permissions object initially.

I suggest you use something like https://github.com/vuejs/vue-async-data. It allows you to get data asynchronously (e.g. with vue-resource) and gives you a way to hide components content until loading the data has finished.

Though you can easily simulate this on your own:

data: function () {
  return { loaded: false, permissions: {} }
},
created() {
  return this.$http(...).then(function (result) {
    this.permissions = result.data.permissions // or however your data is
    this.loaded = true
  })
}

and in the template, use v-if="loaded" on a wrapping div to hide the content until permissions are actually loaded.

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

1 Comment

This is what I needed, still trying to wrap my head around two-way binding. Thanks!
0

It is because permissions is not Vue path object. Once you pass it as prop it will become one, and you will be able to reference it like that. Could you provide full code for your component for further explanation?

Comments

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.