Allow me to present my current project which involves the creation of a web application that displays data about devices spread across a country. To achieve this, I utilized Vue.js and HighCharts (employing HighMaps for the map component). The image below showcases the progress I've made so far.
https://i.sstatic.net/YHN5y.png
My next objective is to enable end-users to click on a specific region on the map and visualize all the devices within that area. For this functionality, I require the "ID" of the region, referred to as the code in HighMaps, to trigger an ajax request to my database. Furthermore, I intend to transform this new feature into a component for more flexible application usage. Below is a rough sketch illustrating my concept:
https://i.sstatic.net/QsnWH.png
Disregard the black lines in the sketch; the goal is to create a new component adjacent to the map or elsewhere in the application. Here is a snippet of my code, where both the template and script tags are embedded within the same file, following a one-page, one-component pattern. Currently, I have implemented a div with curly brackets to update a variable upon change, for debugging purposes. My primary concern lies in the plotOptions.series.point.events.click section, where referencing the this.foo variable seems to face challenges with updates. I suspect this issue might be related to scoping but require guidance on where to begin investigating.
<template>
<div id="canvasContainer">
<highmaps :options="chartOptions"></highmaps>
<app-componentForDevices><app-componentForDevices>
<div>{{foo}}</div>
</div>
</template>
<script>
import HighCharts from 'vue-highcharts';
import json from '../map.json'
export default {
data: function () {
return {
foo: 'NO',
/* Map */
chartOptions: {
chart: {
map: json, // The map data is taken from the .json file imported above
},
plotOptions: {
series: {
point: {
events: {
click: function () {
this.foo='OK'
}
}
}
},
map: {
joinBy: ['hc-key', 'code'],
allAreas: false,
tooltip: {
headerFormat: '',
pointFormat: '{point.name}: <b>{series.name}</b>'
},
}
},
/* Zoom and move */
mapNavigation: {
enabled: true,
buttonOptions: {
verticalAlign: 'bottom'
}
},
series: [
{
allAreas: true,
showInLegend: false,
},
{
borderColor: '#a0451c',
cursor: 'pointer',
name: 'ERROR',
color: "red",
data: ['it-na', 'it-mi', 'it-mo', 'it-ud'].map(function (code) {
return {code: code};
}),
},
{
borderColor: '#a09e21',
cursor: 'pointer',
name: 'WARNING',
color: "yellow",
data: ['it-ts', 'it-av', 'it-ri'].map(function (code) {
return {code: code};
}),
},
{
borderColor: '#4ea02a',
cursor: 'pointer',
name: "OK",
color: "lightgreen",
data: ['it-pa', 'it-ve', 'it-bo', 'it-ta', 'it-pn'].map(function (code) {
return {code: code};
}),
},
],
}
}
}
}
</script>
<style scoped>
svg{
align-items: center;
}
Your assistance in this matter is greatly appreciated. Thank you!
EDIT
Following @icecream_hobbit's suggestion, I have made progress by utilizing an ECMA6 arrow function, as it allows access to the variable stored in Vue. However, this refinement has caused me to lose access to local arguments like this.name
, which was essential for displaying the selected region. Any insights or solutions to this dilemma would be valuable.
EDITv2
Thanks to @icecream_hobbit, I have successfully achieved the desired functionality. By adding an object within the parentheses, I can now utilize this
for global variables and e
for mouse click events.
events: {
click: (e) => {
this.foo = 'OK'
this.foo = e.point.name
}
}