Reputation: 357
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.
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
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
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