Reputation: 11749
I have a reference to a component
<Gmap ref="mapRef">
In mounted I am doing this, to see the objects are available
mounted(){
let self = this
console.log(self.$refs) // Shows the mapRef object reference
console.log(self.$refs.mapRef) // returns undefined ???
}
self.$refs shows...
mapRef: VueComponent {_uid: 207, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
So then why does self.$refs.mapRef
return undefined??
Even though it's clearly there??
Upvotes: 51
Views: 107159
Reputation: 1
You could add eager
prop to the component, because of lazy loading in vuetify 2.
Upvotes: 0
Reputation: 12545
I had a similar problem getting a ref to a leaflet map instance, try waiting for the "nextTick"
mounted(){
this.$nextTick(()=>{
let self = this
console.log(self.$refs) // Shows the mapRef object reference
console.log(self.$refs.mapRef) // returns undefined ???
});
}
see the docs for more- https://v2.vuejs.org/v2/api/#vm-nextTick and https://v2.vuejs.org/v2/api/#mounted
Upvotes: 25
Reputation: 4464
Seems like you're using: https://github.com/diegoazh/gmap-vue, as the docs says: https://diegoazh.github.io/gmap-vue/#lazy-loading
async mounted() {
await this.$gmapApiPromiseLazy()
...
}
This works perfectly.
Upvotes: 0
Reputation: 1276
Main solution is to make sure your component is not imported dynamically
You'd still need to also avoid wrapping your component with v-if
and use this.$refs.mapRef
in mounted()
, instead of created()
I wasn't using Vue Google Maps plugin/component, but my own custom component
Use:
import CustomComponent from './CustomComponent ';
export default {
components: {
CustomComponent,
},
...
}
Instead of
export default {
components: {
CustomComponent: () => import('./CustomComponent'),
},
...
}
Use this.$refs.mapRef
in mounted()
instead of created()
.
This way, setTimeout()
and this.$nextTick()
not needed
Correct way:
mounted(){
//works! child components were loaded
console.log(this.$refs.mapRef)
}
Wrong way:
created(){
//DON'T DO THIS! child components hasn't loaded
console.log(this.$refs.mapRef)
//might work but it's an unreliable workaround
setTimeout(()=>{
console.log(this.$refs.mapRef)
}, 0);
//might work but it's an unreliable workaround
this.$nextTick(()=>{
console.log(this.$refs.mapRef)
});
}
Do not wrap child component using v-if
, use v-show
instead.
Correct way:
<div v-show="!isLoading">
<GMap ref="mapRef" />
</div>
Wrong way:
<div v-if="!isLoading">
<GMap ref="mapRef" />
</div>
The following are methods I tried but didn't work until I used the methods on top (stopped using dynamic import)
I already put this.$refs.mapRef
in mounted()
tried to wrap it with setTimeout()
and 2 layers of this.$nextTick()
.
It works only on hot reload, but no longer works after a page refresh
mounted(){
setTimeout(()=>{
this.$nextTick(()=>{
this.$nextTick(()=>{
console.log(this.$refs.mapRef) // returns undefined
});
});
}, 0);
}
Thanks to this comment in another answer: How to access to a child method from the parent in vue.js
Upvotes: 15
Reputation: 129
You can use it as follows, though I don't know if in anyway it could break typescript implementation for commercial projects.
(this as any).$refs.mapRef
Upvotes: -5
Reputation: 2329
In my case, I was using ref along with v-for, I missed the fact ref is generated only after v-for is rendered in the dom, and I was using v-for with a state array property which is populated a few seconds after mounted is called and I was trying to access my ref before the populating the state array.
Upvotes: 0
Reputation: 59
You can wrap your function in the $mapPromise
method provided by vue2-google-maps
, which will ensure that the Map has fully rendered before running your code:
let self = this;
self.$refs.mapRef.$mapPromise.then(() => {
console.log(self.$refs.mapRef);
})
This should solve any problem where your code relies the Google Map to be fully rendered in order to run.
*NOTE: $mapPromise
was named $mapCreated
in past versions.
See Docs: https://github.com/Jeson-gk/vue2-google-maps/blob/master/API.md#mapcreated--promisegooglemapsmap
-
The reason why console.log(self.$refs);
was showing the value when you looked, is that self.$refs
is passed by reference. So, by the time you viewed the console, the rest of the data finished loading in a matter of milliseconds. And self.$ref.mapRef
is not passed by reference, so it remains undefined
, as it was during runtime.
Try adding a breakpoint directly after console.log(self.$refs);
and before console.log(self.$refs.mapRef);
and you will probably find that the data had not loaded.
Upvotes: 0
Reputation: 11749
I solved this by using v-show instead of v-if.
I had the component inside a v-if statement.
<div v-if="!isLoading">
<GMap ref="mapRef" />
</div>
I just changed that to v-show
<div v-show="!isLoading">
<GMap ref="mapRef" />
</div>
And now the object is available in mounted(). Still find it strange that the console.log(this.$refs) showed it being available as a key on this.$refs, even though it actually wasn't? Thats strange behaviour.
The other wierd thing was, that even if I tried to access this.$refs.mapRef in my data loading section, AFTER THE DATA WAS LOADED, (ie after isLoading=false), I still couldn't access it. Even though then, it should've been available because the v-if passed.
So v-show solved it, by just hiding the div, instead of not rendereding it. Stupid little workaround.
Upvotes: 59