I realized that there is the same issue with classic javascript. However, I aim to use the v-for
and "'map'+user.id"
, :ref
to dynamically create the longitude, latitude leaflet maps for each bootstrap card. I am wondering how to solve this problem in vue 3.
From the console, I confirm that each block could have a different id but the same class.
I found this post with vuejs2 ref when initiating multiple instances. It's been a while, now the docs illustrates the correct way to use ref
in the method.
Here is the CodeSandBox. (rendering in the localhost, though)
Here is the relevant code:
<template>
<div class="container">
<div class="row">
<div class="col-md-4 mb-3" v-for="user in users" :key="user.id">
<div :id="'map'+user.id" :ref="setItemRef" class="map"></div>
</div>
</div>
</template>
<script>
import users from '@/data/data.js'
import L from 'leaflet'
export default {
data() {
return {
status: true,
users: [],
map: null,
accessToken: "Token shown in the CodeSandBox"
}
},
methods: {
setItemRef(el) {
if (el) {
// reference: https://v3-migration.vuejs.org/breaking-changes/array-refs.html#migration-strategy
// this.itemRefs.push(el)
console.log(el)
this.map = L.map(el).setView([51.505, -0.09], 13);
L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
attribution: 'Map data © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
maxZoom: 18,
id: 'mapbox/streets-v11',
tileSize: 512,
zoomOffset: -1,
accessToken: this.accessToken
}).addTo(this.map);
// this.map.off()
// this.map.remove()
//console.log(this.map)
}
},
},
</script>
<style>
.map {
width: 400px;
height: 400px;
}
</style>
The way I did it is to push the 'map'+user.id
into an array. Then using forEach
to render with different maps. The error I bumped into is because the this.map
always refers to the same instance.
Therefore, the code in the script should be:
<script>
export default {
data() {
return {
status: true,
users: [],
itemRefs:[], // for saving the unique mapid
accessToken: "Your mapbox token"
}
},
methods: {
/**
* instantiate the id to each user to further use
*/
instantiateId() {
this.users.map((user,index) => user.id = index)
},
setItemRef(el) {
if (el) {
// reference: https://v3.vuejs.org/guide/migration/array-refs.html#migration-strategy
//console.log(el)
//console.log(el.id)
this.itemRefs.push(el.id)
}
},
createMap() {
this.itemRefs.forEach(element => {
// console.log(element)
var mymap = L.map(element).setView([51.505, -0.09],13);
L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
attribution: 'Map data © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
maxZoom: 18,
id: 'mapbox/streets-v11',
tileSize: 512,
zoomOffset: -1,
accessToken: this.accessToken
}).addTo(mymap);
});
}
},
mounted() {
this.createMap()
},
}
</script>