Access $refs from other components not in the same level as current component
I'm working on a Vue application. It has a header and then the main content. Nesting and structure as below
TheHeader.vue -> TheLogin.vue
MainContent.vue -> ShoppingCart.vue -> OrderSummary.vue
I need to access an element in TheLogin.vue
from OrderSummary.vue
this.$refs.loginPopover.$emit('open')
gives me an error "Cannot read property '$emit' of undefined"
so obviously I am not able to access $refs
from other components.
The question is how do I get hold of refs from other components? Thanks in advance!
Edit 1 - Found out $refs works with only child components. How do I access elements across components in different level?
Solution 1:
You definitely don't want to be reaching through the hierarchy like that. You are breaking encapsulation. You want a global event bus.
And here's a secret: there's one built in, called $root
. Have your OrderSummary do
this.$root.emit('openPopup');
and set up a listener in your TheLogin's created
hook:
this.$root.on('openPopup', () => this.$emit('open'));
In general, you should try to avoid using refs.
Solution 2:
For anyone who comes here later and wants to access $refs
in parent component, not in this particular case for emitting events since event bus or a store would suffice but let's just say you want to access some element in parent to get it's attributes like clientHeight
, classList
etc. then you could access them like:
this.$parent.$parent.$refs //you can traverse through multiple levels like this to access $ref property at the required level
Solution 3:
You can put a function like this on your component to do this. I put mine in a Mixin:
public findRefByName(refName) {
let obj = this
while (obj) {
if (obj.$refs[refName]) {
return obj.$refs[refName]
}
obj = obj.$parent
}
return undefined
}
I also added some accessors to help:
get mycomponent() {
return this.findRefByName('mycomponent')
}
And once that exists, you can access your component by simply doing:
this.mycomponent