1

I am using this codepen (https://www.amcharts.com/kbase/selecting-countries-map/). It stores clicked countries in an array.

The problem is, I need this dynamic array available globally, so I can share it between components. The array is currently nested within a function in ngOnInit.

Is it possible to update a global array from this nested position? I've tried moving the empty array outside the function, making it equal to a global variable, etc.

Map Component

import { Component, OnInit } from '@angular/core';
import { Router, RouterModule, ActivatedRoute } from '@angular/router';
import { AmChartsService } from "amcharts3-angular2";

declare var AmCharts : any; //we must declare our AmCharts variable, like Google

@Component({
  selector: 'app-map',
  templateUrl: './map.component.html',
  styleUrls: ['./map.component.css']
})

export class MapComponent implements OnInit {

  selectedCountries: any;

  constructor()
 {}


  ngOnInit() {


    var map = AmCharts.makeChart("mapdiv",{
    type: "map",
    theme: "dark",
    projection: "mercator",
    panEventsEnabled : true,
    backgroundColor : "#535364",
    backgroundAlpha : 1,
    zoomControl: {
    zoomControlEnabled : true
    },
    dataProvider : {
    map : "worldHigh",
    getAreasFromMap : true,
    areas :
    []
    },
    areasSettings : {
    autoZoom : false,
    selectable: true,
    color : "#B4B4B7",
    colorSolid : "#84ADE9",
    selectedColor : "#84ADE9",
    outlineColor : "#666666",
    rollOverColor : "#9EC2F7",
    rollOverOutlineColor : "#000000"
  },
    listeners: [{
      "event": "clickMapObject",
      "method": function(e) {

     // Ignore any click not on area
     if (e.mapObject.objectType !== "MapArea")
       return;

     var area = e.mapObject;

     // Toggle showAsSelected
     area.showAsSelected = !area.showAsSelected;
     e.chart.returnInitialColor(area);

     // Update the list
     document.getElementById("selected").innerHTML = JSON.stringify(getSelectedCountries());

   }
 }]
});

    /**
 * Function which extracts currently selected country list.
 * Returns array of country names
 */


function getSelectedCountries() {
  var selected = [];
  for(var i = 0; i < map.dataProvider.areas.length; i++) {
    if(map.dataProvider.areas[i].showAsSelected)
      selected.push(map.dataProvider.areas[i].enTitle);
  }

  return selected;
}



}


}
1
  • by global array what you mean? Commented Apr 12, 2017 at 22:28

2 Answers 2

1

I separated your getSelectedCountries() method outside the ngOnInit(). Than defined map as a component variable, and filled this.selectedCountries with result of method getSelectedCountries().

import { Component, OnInit } from '@angular/core';
import { Router, RouterModule, ActivatedRoute } from '@angular/router';
import { AmChartsService } from "amcharts3-angular2";

declare var AmCharts: any; //we must declare our AmCharts variable, like Google

@Component({
    selector: 'app-map',
    templateUrl: './map.component.html',
    styleUrls: ['./map.component.css']
})

export class MapComponent implements OnInit {

    selectedCountries: any;
    map: any;

    constructor()
    { }


    ngOnInit() {


        this.map = AmCharts.makeChart("mapdiv", {
            type: "map",
            theme: "dark",
            projection: "mercator",
            panEventsEnabled: true,
            backgroundColor: "#535364",
            backgroundAlpha: 1,
            zoomControl: {
                zoomControlEnabled: true
            },
            dataProvider: {
                map: "worldHigh",
                getAreasFromMap: true,
                areas:
                []
            },
            areasSettings: {
                autoZoom: false,
                selectable: true,
                color: "#B4B4B7",
                colorSolid: "#84ADE9",
                selectedColor: "#84ADE9",
                outlineColor: "#666666",
                rollOverColor: "#9EC2F7",
                rollOverOutlineColor: "#000000"
            },
            listeners: [{
                "event": "clickMapObject",
                "method": (e) => {

                    // Ignore any click not on area
                    if (e.mapObject.objectType !== "MapArea")
                        return;

                    var area = e.mapObject;

                    // Toggle showAsSelected
                    area.showAsSelected = !area.showAsSelected;
                    e.chart.returnInitialColor(area);

                    // Update the list
                    let result = getSelectedCountries(this.map);
                    document.getElementById("selected").innerHTML = JSON.stringify(result );
                    this.selectedCountries = result;

                }
            }]
        });

        /**
     * Function which extracts currently selected country list.
     * Returns array of country names
     */






    }

    getSelectedCountries(map: any) {
            var selected = [];
            for (var i = 0; i < map.dataProvider.areas.length; i++) {
                if (map.dataProvider.areas[i].showAsSelected)
                    selected.push(map.dataProvider.areas[i].enTitle);
            }

            return selected;
        }


}
Sign up to request clarification or add additional context in comments.

2 Comments

It works great, and I learned a couple things. Thanks a lot for your help - I appreciate it!!!
Glad it helped.
0

The best way is to create service and provide it in your main module that you bootstrap:

Shared service

@Injectable
export class AppService {
   sharableData: string;

   constructor(){
       this.sharableData = 'some data';
   }
}

Main bootstrap component

@Component({
  selector: 'my-app',
  template: '{{_appService.sharableData}}',
})
export class App { 

  constructor(private _appService: AppService) {}
}

@NgModule({
  imports: [ BrowserModule, FormsModule ],
  declarations: [ App, AnotherComponent ],
  bootstrap: [ App ],
  provide: [
     AppService
  ]
})
export class AppModule {}

Another compoent

@Component({
  selector: 'another-component',
  template: '{{_appService.sharableData}}',
})
export class AnotherComponent { 

  constructor(private _appService: AppService) {}
}

As you can see two components are declared inside same module. These two components share same reference to AppService because it is provided. This is also the case if you have routed components inside router-outlet.

2 Comments

Thanks for your help. I updated my post with my map component to show you what I mean. My 'selected' variable is nested in the getSelectedCountries() function. This array updates the dom in the list updater nested in the map variable above. I would like to be able to dynamically store that array outside of the function. If it's nested in the function, would I still be able to do that from the service?
Aha, ok. So first thing, dont use function() {}, use () => {} since that will get you out of the trouble called closure. var map should be defined as a component variable, not as local variable in ngOnInit. I will make another answer since this will be a different code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.