2
votes

I'm discovering Highcharts / Highmaps and for now, I would like to reproduce some demo examples on my machine using Angular 6, but I can't make it work.

The official JS example is here : https://www.highcharts.com/maps/demo/map-drilldown (you can see the code by clicking "Edit in CodePen")

I've tried to adapt the example like this :

import { Component, OnInit } from '@angular/core';
import { Highcharts, MapChart } from 'angular-highcharts';

require('highcharts/modules/map')(Highcharts);

@Component({
  selector: 'app-demo-map-drilldown',
  templateUrl: './demo-map-drilldown.component.html',
  styleUrls: ['./demo-map-drilldown.component.css']
})
export class DemoMapDrilldownComponent implements OnInit {

  private chart: MapChart;

  constructor(private httpClient: HttpClient) { }

  ngOnInit() {
    let data = Highcharts.geojson(Highcharts.maps['countries/us/us-all']);
    let separators = Highcharts.geojson(Highcharts.maps['countries/us/us-all'], 'mapline');

    // Set drilldown pointers
    data.forEach((element, i) => {
      element.drilldown = element.properties['hc-key'];
      element.value = i; // Non-random bogus data
    });

    // Instantiate the map
    Highcharts.mapChart('container', {
      chart: {
        events: {
          drilldown: function (e) {
            if (!e.seriesOptions) {
              let chart = this;
              let mapKey = 'countries/us/' + e.point.drilldown + '-all';
              // Handle error, the timeout is cleared on success
              let fail = setTimeout(function () {
                if (!Highcharts.maps[mapKey]) {
                  chart.showLoading('<i class="icon-frown"></i> Failed loading ' + e.point.name);
                  fail = setTimeout(function () {
                    chart.hideLoading();
                  }, 1000);
                }
              }, 3000);

              // Show the spinner
              chart.showLoading('<i class="icon-spinner icon-spin icon-3x"></i>'); // Font Awesome spinner

              //data = Highcharts.geojson(Highcharts.maps[mapKey]);
              data = Highcharts.maps[mapKey];

              // Set a non-random bogus value
              data.forEach((element, i) => {
                element.value = i; // Non-random bogus data
              });

              // Hide loading and add series
              chart.hideLoading();
              clearTimeout(fail);
              chart.addSeriesAsDrilldown(e.point, {
                name: e.point.name,
                data: data,
                dataLabels: {
                  enabled: true,
                  format: '{point.name}'
                }
              });

            }

            this.setTitle(null, { text: e.point.name });
          },
          drillup: function () {
            this.setTitle(null, { text: '' });
          }
        }
      },

      title: {
        text: 'Highcharts Map Drilldown'
      },

      subtitle: {
        text: '',
        floating: true,
        align: 'right',
        y: 50,
        style: {
          fontSize: '16px'
        }
      },

      legend: {
        layout: 'vertical',
        align: 'right',
        verticalAlign: 'middle'
      },

      colorAxis: {
        min: 0,
        minColor: '#E6E7E8',
        maxColor: '#005645'
      },

      mapNavigation: {
        enabled: true,
        buttonOptions: {
          verticalAlign: 'bottom'
        }
      },

      plotOptions: {
        map: {
          states: {
            hover: {
              color: '#EEDD66'
            }
          }
        }
      },

      series: [{
        data: data,
        name: 'USA',
        dataLabels: {
          enabled: true,
          format: '{point.properties.postal-code}'
        }
        }, {
          type: 'mapline',
          data: separators,
          color: 'silver',
          enableMouseTracking: false,
          animation: {
            duration: 500
          }
      }],

      drilldown: {
        activeDataLabelStyle: {
          color: '#FFFFFF',
          textDecoration: 'none',
          textOutline: '1px #000000'
        },
        drillUpButton: {
          relativeTo: 'spacingBox',
          position: {
            x: 0,
            y: 60
          }
        }
      }
    });
  }
}

But no luck so far. Here I get the error geojson is undefined and my editor (Visual Studio Code) underlines all my calls to Highcharts (.geojson, .maps, .mapChart).

My app.module.ts file looks like this :

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { ChartModule, HIGHCHARTS_MODULES } from 'angular-highcharts';
import * as more from 'highcharts/highcharts-more.src';
import * as exporting from 'highcharts/modules/exporting.src';
import * as highstock from 'highcharts/modules/stock.src';
import * as highmaps from 'highcharts/modules/map.src';
import * as drilldown from 'highcharts/modules/drilldown.src';
import * as data from 'highcharts/modules/data.src';
import * as exportdata from 'highcharts/modules/export-data.src';
import * as offline from 'highcharts/modules/offline-exporting.src';

import { AppComponent } from './app.component';
import { DemoMapDrilldownComponent } from './demo-map-drilldown/demo-map-drilldown.component';

@NgModule({
  declarations: [
    AppComponent,
    DemoMapDrilldownComponent,
  ],
  imports: [
    BrowserModule,
    ChartModule,
  ],
  providers: [
    {
      provide: HIGHCHARTS_MODULES,
      useFactory: () => [more, exporting, highstock, highmaps, drilldown, data, exportdata, offline]
    }, // add as factory to your providers
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

As you can see, I've tried importing various modules from inside Highcharts (based on several tutorials), but with no improvement...

I feel completely lost about Highcharts. Obviously something is wrong in my setup and/or in my use of this framework, but the documentation is not helpful at all and I couldn't find any complete, detailed Angular tutorial.

Can somebody help me at least to run this official example in an Angular app ?

UPDATE : Thanks to @daniel_s, I'm now using the official wrapper highcharts-angular and got rid of the editor errors. I ran npm install highcharts-angular --save then npm install highcharts --save in the console in a new project.

You can see the project here : https://codesandbox.io/s/38o5n9qor1 (I added highcharts-angular, highcharts and highcharts-map as dependencies in the sandbox) In the console, we get the error :

ERROR TypeError: "a is undefined"
geojson             https://38o5n9qor1.codesandbox.io/node_modules/highcharts/highmaps.js:435:407
ngAfterViewInit     https://38o5n9qor1.codesandbox.io/src/app/official-example/official-example.component.ts:18:20

Can you check and help me correct my code ?

2
Have you tried to use our official Highcharts wrapper for Angular? Here is the npm package link: npmjs.com/package/highcharts-angular . I suspect your implementation is a bit wrong, but I only guessing. Could you try to prepare the example of your app in some code sandbox like StackBlitz or CodeSandbox? If yes, please provide me with it.daniel_s
@daniel_s I feel so silly. I've been using npmjs.com/package/angular-highcharts (which was the first Google result I found) instead of highcharts-angular, without suspecting it wasn't the official wrapper. With highcharts-angular, the editor errors have disappeared ! Thank you very very much ! So now my problem is to rewrite the example as an Angular component. Please see my edit.Daneel

2 Answers

2
votes

It's not working because you don't import any map in your project at all. Unfortunately, there is no npm package with all maps, but you can manually create a file with maps which you need, and import the files directly to your project. Here is the example of how to add the map to your project: https://codesandbox.io/s/vm58jk5005

Best regards!

2
votes

I know this might not be the exact answer, but in case if someone will have the interest to draw the US Map example from Highcharts official documentation, you might encounter issues such as map not rendering or lots of console errors.


Here I want to briefly write a few steps to make that example work just in case if you have the same situation.

Steps:
1) Download (or use CDN if you prefer) US-ALL & US-CAPITALS from here.

2) Once that done put the JSON files to your project data folder (or anywhere else you prefer).

3) Before map rendering try to make sure that you can get JSON data with httpClient:

  this._httpClient.get('data/us-all.json').first().subscribe((map: any) => {
      this._httpClient.get('data/us-capitals.json').first().subscribe((json: any) => {
...

4) Now use below code to render the map:

HTML

  <div [chart]="mapChart"
       style="min-width: 60vw; max-width: 100vw; height: 70vh; margin: 0 auto"></div>

Typescript/JS

...  

 public ngOnInit(): void {
    MapModule(Highcharts)

    this._httpClient.get('data/us-all.json').first().subscribe((map: any) => {
      this._httpClient.get('data/us-capitals.json').first().subscribe((json: any) => {
        const data: any[] = []
        forEach(USCapitals.default, (elm) => {
          elm.z = elm.population
          data.push(elm)
        })

        this.mapChart = new MapChart({
          title: {
            text: 'Highmaps lat/lon demo'
          },

          tooltip: {
            pointFormat: '{point.capital}, {point.parentState}<br>' +
              'Lat: {point.lat}<br>' +
              'Lon: {point.lon}<br>' +
              'Population: {point.population}'
          },
          xAxis: {
            crosshair: {
              zIndex: 5,
              dashStyle: 'dot',
              snap: false,
              color: 'gray'
            }
          },
          yAxis: {
            crosshair: {
              zIndex: 5,
              dashStyle: 'dot',
              snap: false,
              color: 'gray'
            }
          },
          mapNavigation: {
          enabled: true,
            buttonOptions: {
              alignTo: 'spacingBox'
            }
          },
          legend: {
            enabled: true
          },
          colorAxis: {
            min: 0
          },
          series: [
          {
             name: 'Basemap',
             mapData: USMap.default,
             borderColor: '#606060',
             nullColor: 'rgba(200, 200, 200, 0.2)',
             showInLegend: false
          } as Highcharts.SeriesMapOptions,
          {
             type: 'mapbubble',
             dataLabels: {
               enabled: true,
               format: '{point.capital}'
             },
             name: 'Enrolment by States',
             data: data,
             maxSize: '12%',
             color: Highcharts.getOptions().colors[ 0 ],
             point: {
               events: {
                  click: event => {
                    alert('you have clicked on map bubble.')
                  }
               }
             }
          },
          {
            name: 'Separators',
            type: 'mapline',
            data: Highcharts.geojson(USMap.default, 'mapline'),
            color: '#101010',
            enableMouseTracking: false,
            showInLegend: false
          }
         ]
        })
      })
    })
  }

The above is enough to see the basic US map with states.


UPDATE

You can also use direct JSON importing like it is written here.