0

I have a Vue instance with two components. If the user clicks on a button in the second component I want to hide the template of first ones.

I have this code:

<div id="app">
    <mycomp-one :active="active"></mycomp-one>
    <mycomp-two></mycomp-two>
</div>

<template id="mycomponent-one">
    <div v-show="!active">
        <!-- ... --->
    </div>
</template>

<template id="mycomponent-two">
    <button v-on:click="setActive">Click Me</button>
</template>

With this script code:

Vue.component('mycomp-one', {
    template: '#mycompnent-one',
    // etc...
});
Vue.component('mycomp-two', {
    template: '#mycomponent-two',
    data: function() {
        return {
            active: false
        };
    },
    methods: {
        setActive: function() {
            this.$parent.$options.methods.setActive();
        },
    },
});
new Vue({
    el:'#app',
    data:{
        active: false
    },
    methods: {
        setActive: function() {
            this.active = !this.active;
        },
    },
});

If the button is clicked it working good to pass the information from the component to the instance. But here is stopping the data flow, the mycomp-one component did not get the change. How can I fix that? I want to hide the mycomp-one if the active is true.

1 Answer 1

2

this.$parent.$options.methods.setActive() is not a method bound to the Vue. I'm not sure how you got here, but this is not how you call a method on the parent.

console.clear()
Vue.component('mycomp-one', {
    props:["active"],
    template: '#mycomponent-one',
});
Vue.component('mycomp-two', {
    template: '#mycomponent-two',
    data: function() {
        return {
            active: false
        };
    },
    methods: {
        setActive: function() {
            this.$parent.setActive();
        },
    },
});
new Vue({
    el:'#app',
    data:{
        active: false
    },
    methods: {
        setActive: function() {
            this.active = !this.active;
        },
    },
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.js"></script>
<div id="app">
    <mycomp-one :active="active"></mycomp-one>
    <mycomp-two></mycomp-two>
</div>

<template id="mycomponent-one">
    <div v-show="!active">
       Stuff
    </div>
</template>

<template id="mycomponent-two">
    <button v-on:click="setActive">Click Me</button>
</template>

Beyond that, components shouldn't call methods on their parent. They should emit events the parent listens to. This is covered well in the documentation.

console.clear()
Vue.component('mycomp-one', {
    props:["active"],
    template: '#mycomponent-one',
});
Vue.component('mycomp-two', {
    template: '#mycomponent-two',
    data: function() {
        return {
            active: false
        };
    },
    methods: {
        setActive: function() {
            this.active = !this.active
            this.$emit("set-active", this.active)
        },
    },
});
new Vue({
    el:'#app',
    data:{
        active: false
    },
    methods: {
        setActive: function() {
            this.active = !this.active;
        },
    },
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.js"></script>
<div id="app">
    <mycomp-one :active="active"></mycomp-one>
    <mycomp-two @set-active="active = $event"></mycomp-two>
</div>

<template id="mycomponent-one">
    <div v-show="!active">
       Stuff
    </div>
</template>

<template id="mycomponent-two">
    <button v-on:click="setActive">Click Me</button>
</template>

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

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.