perkola's avatar

Vue.js acces parent methods

I have a Vue object tied to a div and within that div i have a component. From the component I want to access methods of the parent. The child component contains buttons with handlers that should call methods from the parent.

<div id="parent">
    <child-component></child-component>
</div>

I've found out that the parent can be accessed via vm.$parent but when i try to call a method like vm.$parent.someParentMethod() I get undefined... Any tips?

0 likes
23 replies
bestmomo's avatar

Did you define the parent property in child component ?

perkola's avatar

@bestmomo I'm not sure what you mean but I don't think so. The problem is that I will use the same component inside many different parent objects so I want to be able to access any parent the component might have.

kfirba's avatar

@perkola Use props:

new Vue({
    el: '#parent',
    methods: {
        first: function() {},
        second: function() {},
        another: function() {}
    }
});

Vue.component('child-component', function() {
    props: ['first', 'second', 'third'],
    // the rest
});

// in your markup:
<div id="parent">
    <child-component first=first second=second third=another></child-component>
</div>
2 likes
perkola's avatar

@kfirba thanks I will try that soon! But is there a quick way to call a parent method from a component method?

new Vue({
    el: '#parent',
    methods: {
        someParentMethod(data) {}
    }
});

Vue.component('child-component', function() {
    methods: {
        someChildMethod() {
            var data = 'test';
            this.$parent.someParentMethod(data) // How do I call a parent method?
        }
    }
});

// Markup
<div id="parent">
    <child-component></child-component>
</div>
kfirba's avatar

@perkola I'm not aware to such thing. Try console.log() the this.$parent and see what attributes are exposed for your usage including methods and see if you can gain an access to the parent's attributes and methods. I still think that using the props is the best way to go about this.

1 like
bestmomo's avatar
Level 52

Not the more elegant :

this.$parent.$options.methods.someParentMethod(data)
8 likes
perkola's avatar

@kfirba @bestmomo I have access to several attributes and

this.$parent.$options.methods.someParentMethod(data)

seems to work, but is has to be a better and more neat way to achieve the same result? I'll stick with this for now. Thanks :-)

bestmomo's avatar

@perkola Another way is to not use hierarchy :

var vm = new Vue({
    el: '#parent',
    methods: {
        someParentMethod(data) {}
    }
});

Vue.component('child-component', function() {
    methods: {
        someChildMethod() {
            var data = 'test';
            vm.someParentMethod(data) 
        }
    }
});

// Markup
<div id="parent">
    <child-component></child-component>
</div>
3 likes
perkola's avatar

@bestmomo with this approach I can't call a method on a generic parent. I want me component to call a method on the parent Vue without "knowing" which Vue. I might have parent1 and parent2 and i can't both name them vm :/

bestmomo's avatar

@perkola I think there is something weird that a child needs a parent function. Maybe you may use event system to achieve that.

1 like
perkola's avatar

@bestmomo I agree. I've read about Vue's event system but I can't figure out how to achieve what i described.

bestmomo's avatar

@perkola

Vue's event system is simple. In child use a dispatch :

this.$dispatch('child-coucou', this);

And listen in parent :

this.$on('child-coucou', function (child) {
  // Make something there with child reference
})
mkr's avatar

@bestmomo And how to pass data from nth child to root parent? Is there better way than this.$dispatch this.$on chaining?

bestmomo's avatar

@mkr I dont know another method and vue.js documentation doesn't mention one.

D9705996's avatar

As much as a pita it might be i would look to remove anything not 1.x.x from your vue code.

I spent hours looking a components and events with 0.12.x and even the betas and ended up with an absolute mess. The official release just works. Using dispath and broadcast events.

Hardest part is building ghe hierarchy

tinymondo's avatar

If your parent is the root, you can use: this.$root.yourMethod()

belisar's avatar

I would go with using the event system. In your listeners, if you want the event to propagate upwards after the first response return true and the event propagation will not stop at the first response, going up the root.

//on the child. payload is just some data you want to pass along if any
...
    this.$dispatch('childIsCalling', payload)

//on the parent(s). other parents up the chain (the parent's 
//parent will also respond if true is returned
events: {
    childIsCalling: function (payload) {
        this.something = payload;
    return true;
    }
}

//or other wise
events: {
    childIsCalling: 'handleChildCall'
}

methods: {
    handleChildCall: function (payload) {
        this.something = payload;
        return true;
    }
}
1 like
commandantp's avatar

@belisar do you know if the disptach event can return a promise? It would be great to have $dispatch().then(do ...) ?

Thanks!

feryardiant's avatar

Just in case someone still finding an alternative

// Child component
Vue.component('child', {
    props: ['label'],
    template: `<button @click="$parent.someMethod">{{ label }}</button>`
});

// Parent component
const parent = vue({
    el: '#app',

    // Some codes

    methods: {
        someMethod () {
            // do something.
        }
    }
})
1 like
pilat's avatar

The case, like this, when you have a parent, full with useful methods, whom you want to use in various children… I believe it's exactly the time to add a global store, like "vuex", into your app.

alphaelf's avatar

another way for vue 2

in child component use this.$emit('eventName'):

methods:{
    openMenu(){
        this.$emit('openMenu')
    }
}

and in parent component use @eventName attribute:

<child @openMenu="main_menu=true"></child> // or call your method
dangdangHellen's avatar

yes, we have access to read the property of parent component using this.$parent, but do we have the access to change this property of parent component using this.$parent?

Please or to participate in this conversation.