How to update global data in clickMapObject listener from AmChart

纵然是瞬间 提交于 2019-12-11 17:53:17

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!