Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue - instance data is not defined

I have a menu of topics (e.g. "About us", "Support") and I want to be able to tell what topic is active right now. When a topic is clicked it will become the active one. Think of it as a substitute for a router that will set an active route. This is not possible in my case since I'm working in SharePoint 2010... in a content editor. So I made the decision to have an activeTopic variable in my Vue instance.

The Vue instance

new Vue({
    el: '#app',
    data: {
        activeTopic: '',
    }
});

This is because the activeTopic has to update another component and show some data based on the active topic. Like a router showing a child route.

The topic component

Vue.component('topic', {
    props: ["title"],
    methods: {
        setActiveTopic: function (title) {
            activeTopic = title;
        },
        isActiveTopic: function (title) {
            return activeTopic == title;
        }
    },
    template: `
        <div v-bind:class="{active: isActiveTopic(title)}" v-on:click="setActiveTopic(title)">
            <p v-text="title"></p>
        </div>
    `
});

The setActiveTopic function works as it should when I click it; it updates the activeTopic. But the isActiveTopic function gives me this error:

Error in render: "ReferenceError: activeTopic is not defined"

What I don't understand is that I can edit the activeTopic variable but I can't make a comparison? I've tried setting a default value but it still says it is undefined.

like image 307
Mozina Avatar asked Jan 28 '23 13:01

Mozina


1 Answers

activeTopic should be assigned to the Vue component by setting and reading this.activeTopic. As is, you have two independent activeTopic variables scoped within each of your component methods.

You'll also want to include activeTopic in the component's data block, rather than on the Vue object itself, since it's specific to the component.

(If there's a reason to put that variable on the Vue object you would either want to pass it down to the component as a prop, or else access it directly as Vue.activeTopic instead of this.activeTopic. I'm honestly not certain whether Vue would treat that last structure as a reactive value within components -- I've never had a reason to try that, and can't think of a situation where that'd be a reasonable architecture.)

Vue.component('topic', {
    props: ["title"],
    data() { return {
      activeTopic: ''
    }},
    methods: {
        setActiveTopic(title) {
            this.activeTopic = title;
        },
        isActiveTopic(title) {
            return this.activeTopic == title;
        }
    },
    template: `
        <div v-bind:class="{active: isActiveTopic(title)}" v-on:click="setActiveTopic(title)">
            <p v-text="title"></p>
        </div>
    `
});
like image 82
Daniel Beck Avatar answered Feb 05 '23 16:02

Daniel Beck