universesurfer
universesurfer

Reputation: 357

Is it possible to update a global array from a dynamically created array inside an ngOnInit?

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;
}



}


}

Upvotes: 1

Views: 1124

Answers (2)

Mario Petrovic
Mario Petrovic

Reputation: 8352

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;
        }


}

Upvotes: 1

Mario Petrovic
Mario Petrovic

Reputation: 8352

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.

Upvotes: 0

Related Questions