问题
I'm learning about AmChart js
lib and I have some doubts.
I have one map that show all devices registered in my database (look the print below)
So, I would like to implement one functionality for when the user clicks on the bubble from one country in the map, the table list is filtered by country, so, in the device, table should show only devices from the country of the bubble that user clicked.
for to do this filter when a user clicks in the bubble, I'm using the addListener from Amchart (clickjMapObject
) as the example below.
this.map.addListener('clickMapObject', function (event) {
console.log(event);
console.log(this.deviceList).
});
the console.log(event) it's working, but When I try to print "deviceList"
not working. I get the following error:
ERROR TypeError: Cannot read property 'devicesList' of undefined
I don't know if it's possible to access global array in the listener, So, I don't know what's the problem. Could you please help me?
follow my complete code below. (in this code you can see how to I populate the "deviceList"
)
export class DevicesLocationComponent implements OnInit {
public devicesList: Device[];
public images = [];
public country_location = [];
public map: any;
@ViewChild(DatatableComponent) table: DatatableComponent;
constructor(private http: HttpClient, private deviceService: DeviceService)
{
this.getCountryLocationJSON().subscribe(data => {
this.country_location = data;
});
}
/**
* Build initial the chart and load devices location
*
* @memberof DevicesLocationComponent
*/
public ngOnInit() {
this.loadDeviceDataTable();
}
/**
* This function is responsible to load datatable with devices data
*/
private loadDeviceDataTable() {
// load last used devices data
this.deviceService.getAllDevices()
.subscribe(((listDevices: Device[]) => {
this.devicesList = listDevices;
this.buildMapChart();
}));
}
/**
* This function is responsible to build the map chart after load devices data on datatable.
*/
private buildMapChart() {
// get min and max values for define bubble size frm map chart
const minBulletSize = 10;
const maxBulletSize = 40;
let min = Infinity;
let max = -Infinity;
for (const key in this.tardisDevicesGrouped) {
if (this.tardisDevicesGrouped.hasOwnProperty(key)) {
const value = this.tardisDevicesGrouped[key].length;
if ( value < min ) {
min = value;
}
if ( value > max ) {
max = value;
}
}
}
// it's better to use circle square to show difference between values, not a radius
const maxSquare = maxBulletSize * maxBulletSize * 2 * Math.PI;
const minSquare = minBulletSize * minBulletSize * 2 * Math.PI;
// create circle for each country
for (const key in this.tardisDevicesGrouped) {
if (this.tardisDevicesGrouped.hasOwnProperty(key)) {
const value = this.tardisDevicesGrouped[key].length;
const country_location = this.getLatLongCountry(key);
// calculate size of a bubble
let square = ( value - min ) / ( max - min ) * ( maxSquare - minSquare ) + minSquare;
if ( square < minSquare ) {
square = minSquare;
}
const size = Math.sqrt( square / ( Math.PI * 2 ) );
// set each bubble size, value and colors for each country
this.images.push( {
'type': 'circle',
'theme': 'light',
'width': size,
'height': size,
'longitude': country_location.longitude,
'latitude': country_location.latitude,
'color': country_location.color,
'title': country_location.country_name,
'selectable': true,
'value': value
});
}
}
this.map = AmCharts.makeChart('allocation-map', {
'type': 'map',
'hideCredits': true,
'theme': 'light',
'colorSteps': 10,
'dataProvider': {
'map': 'worldLow',
'images': this.images,
'zoomLevel': 1.0,
'zoomLongitude': 10,
'zoomLatitude': 52
},
'areasSettings': {
'autoZoom': true,
'selectable': true
}
});
console.log(this.devicesList); // It's working
this.map.addListener('clickMapObject', function (event) {
console.log(event);
console.log(this.devicesList); // It's not working
});
}
}
回答1:
Above the event listener you should declare a variable storing the current scope
var self = this
Then inside the function triggered at the event you should change the this reference to self
console.log(self.devicesList);
At the end your code should look like this:
console.log(this.devicesList); // It's working
var self = this;
this.map.addListener('clickMapObject', function (event) {
console.log(event);
console.log(self.devicesList); // Now it will work
});
}
This happens because the scope is changing depending on where you are, so "this" doesn't mean the same inside an event listener than inside a component, the reference changes
来源:https://stackoverflow.com/questions/53598764/how-to-update-global-data-in-clickmapobject-listener-from-amchart