2

I'm using the ngx-leaflet demo to try and get a GeoJson from a get request to display on the LeafLet Map. I have built a valid GeoJson using http://geojson.io/, and double checked it using the http://geojsonlint.com/ (Thanks for those tools guys)

We have no errors in the compilation or displaying in the console log. Serves fine but our geojson object is nowhere to be found.

I'm just looking to display the geojson data on the map. Any help or advice is appreciated.

Angular CLI: 1.6.5
Node: 8.3.0
OS: darwin x64
Angular: 5.2.1
... common, compiler, compiler-cli, core, forms, http
... language-service, platform-browser, platform-browser-dynamic
... router

@angular/animations: 5.2.2
@angular/cdk: 5.1.1
@angular/cli: 1.6.5
@angular/material: 5.1.1
@angular-devkit/build-optimizer: 0.0.41
@angular-devkit/core: 0.0.28
@angular-devkit/schematics: 0.0.51
@ngtools/json-schema: 1.1.0
@ngtools/webpack: 1.9.5
@schematics/angular: 0.1.16
typescript: 2.5.3
webpack: 3.10.0

<div leaflet style="height: 600px;"
     [leafletOptions]="options"
     [leafletLayers]="layers"
     [leafletLayersControl]="layersControl">
</div>

State Component

import { Component, OnInit } from '@angular/core';
import { StateService } from "../state.service";
import {tileLayer, Layer, latLng} from "leaflet";
import {HttpClient} from "@angular/common/http";
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import { LeafletLayersDemoModel } from './layers-demo.model';
import * as L from 'leaflet';


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

  public geo_json_data;

  constructor(private state_service:StateService, public http:HttpClient) {
    this.apply();
  }

  LAYER_OSM = {
    id: 'openstreetmap',
    name: 'Open Street Map',
    enabled: false,
    layer: tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
      maxZoom: 18,
      attribution: 'Open Street Map'
    })
  };

  geoJSON = {
    id: 'geoJSON',
    name: 'Geo JSON Polygon',
    enabled: true,
    layer: L.geoJSON(this.geo_json_data)
  };


  model = new LeafletLayersDemoModel(
    [ this.LAYER_OSM],
    this.LAYER_OSM.id,
    [ this.geoJSON ]
  );

  layers: Layer[];
  layersControl = {
    baseLayers: {
      'Open Street Map': this.LAYER_OSM.layer
    },
    overlays: {
      GeoJSON: this.geoJSON.layer
    }
  };
  options = {
    zoom: 6,
    center: latLng(41.2033, -74.2179)
  };


  apply() {

    // Get the active base layer
    const baseLayer = this.model.baseLayers.find((l: any) => (l.id === this.model.baseLayer));

    // Get all the active overlay layers
    const newLayers = this.model.overlayLayers
      .filter((l: any) => l.enabled)
      .map((l: any) => l.layer);
    newLayers.unshift(baseLayer.layer);

    this.layers = newLayers;

    return false;
  }



  ngOnInit() {
    console.log(this.state_service.state_id);
    this.http.get('http://localhost:4200/assets/data/pa.geojson')
      .subscribe((data) => {
          this.geo_json_data = data;
          console.log(this.geo_json_data);
        },
        error => {
          console.log(error.text());
          alert('GEO JSON GET FAILED');
        });
  }


}
Nicholas Genco
  • 27
  • 1
  • 10
  • bit late now but see the solution here...https://stackoverflow.com/questions/52832684/leaflet-import-geojson-angular-6 ... much simpler... i had the same issue as you and couldn't believe the complicated solutions I was seeing – 72GM Oct 15 '20 at 17:47

1 Answers1

3

You should try initialise the layers var (and others) in subscribe, after receiving the data: Here is an example: You should install the following:

ng new geojsondemo
cd geojsondemo/

npm install leaflet --save
npm install @types/leaflet --save-dev
npm install @asymmetrik/ngx-leaflet --save
npm install leaflet-providers --save
npm install @types/leaflet-providers --save-dev

Your app.module.ts should like this:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { LeafletModule } from '@asymmetrik/ngx-leaflet';

import { AppComponent } from './app.component';

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule,
        LeafletModule,
        HttpClientModule
    ],
    providers: [],
    bootstrap: [AppComponent]
})
export class AppModule { }

Your app.component.html should look like this:

<div leaflet style="height: 300px"
     [leafletLayers]="layers"
     [leafletLayersControl]="layersControl"
     [leafletCenter]="center"
     [leafletFitBounds]="fitBounds"></div>

Your app.component.ts should look like this:

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Layer, tileLayer, geoJSON, LayerOptions } from 'leaflet';
import 'leaflet-providers';

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

    layers: Layer[];
    layersControl: any;
    center = [59.9386300, 30.3141300];
    fitBounds = [[60.2448369, 29.6998985], [59.6337832, 30.254172]];

    constructor(private http: HttpClient) { }

    ngOnInit() {
        this.http.get<any>('/assets/geojson/admin_level_4.geojson')
            .subscribe(geo1 => {
                this.http.get<any>('/assets/geojson/admin_level_5.geojson')
                    .subscribe(geo2 => {
                        let defaultBaseLayer = tileLayer.provider('OpenStreetMap.Mapnik');
                        let defaultOverlay = geoJSON(geo1);
                        this.layers = [
                            defaultBaseLayer,
                            defaultOverlay
                        ];
                        this.layersControl = {
                            baseLayers: {
                                'OpenStreetMap Mapnik': defaultBaseLayer,
                                'OpenStreetMap BlackAndWhite': tileLayer.provider('OpenStreetMap.BlackAndWhite')
                            },
                            overlays: {
                                'Overlay One': defaultOverlay,
                                'Overlay Two': geoJSON(geo2)
                            }
                        };
                    });

            });
    }

}

There are two base layers and two overlays. For base layes I used leaflet-prividers (much cleaner code). For overlay I used two geojson files. Provide your own and change the paths. Also provide a center and a fitBounds. And don't forget to add leaflet.css to .angular-cli.json like so "styles": ["../node_modules/leaflet/dist/leaflet.css","styles.css"]

Sergiu Starciuc
  • 532
  • 5
  • 9
  • Thanks for your comment, I tried to use your solution. What I did was initialize all variables, and have the subscribe method also call the apply function. The map went completely blank. Then I tried to use public variables which resulted in "Error: Uncaught (in promise): TypeError: Cannot read property 'baselayers' of undefined". If there is something I'm missing of you could provide an example that would be great. – Nicholas Genco Mar 04 '18 at 01:13