1

I have a problem where i try to use the onEachFeature Methode for a geoJSON Layer. I try to assign a click listener to every Feature. The problem is that i always get that error when i click at a feature:

Uncaught TypeError: Cannot read property 'detectChanges' of undefined

I can think of that this is because the Layer is assigned before the constructor runs but to do that in the ngOnInit function wont worked either. Would be cool if ther is a good way to do that :)

  constructor(private changeDetector: ChangeDetectorRef){}

  fitBounds: LatLngBounds;
  geoLayer = geoJSON(statesData, {onEachFeature : this.onEachFeature});

  onEachFeature(feature , layer) {
    layer.on('click', <LeafletMouseEvent> (e) => {
        this.fitBounds = [
            [0.712, -74.227],
            [0.774, -74.125]
        ];
        this.changeDetector.detectChanges();
    });
  }

  layer: Layer[] = [];
  fitBounds: LatLngBounds;
  
  onEachFeature(feature , layer : geoJSON) {
    layer.on('click', <LeafletMouseEvent> (e) => {
        console.log("tets"+e.target.getBounds().toBBoxString());
        this.fitBounds = [
            [0.712, -74.227],
            [0.774, -74.125]
        ];
        this.changeDetector.detectChanges();
    });
  }
  
constructor(private changeDetector: ChangeDetectorRef){}

ngOnInit() {
      let geoLayer = geoJSON(statesData, {onEachFeature : this.onEachFeature});
      this.layer.push(geoLayer);
}
TheSorm
  • 137
  • 12
  • Possible duplicate of [Leaflet- marker click event works fine but methods of the class are undefined in the callback function](https://stackoverflow.com/questions/48170860/leaflet-marker-click-event-works-fine-but-methods-of-the-class-are-undefined-in) – ghybs Feb 18 '18 at 17:15

1 Answers1

7

You need to make sure that the right this is accessible in your callback. You do this using function.bind() in Javascript. See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

constructor(private changeDetector: ChangeDetectorRef){}

fitBounds: LatLngBounds;
geoLayer = geoJSON(statesData, {
    // Need to bind the proper this context
    onEachFeature : this.onEachFeature.bind(this)
});

onEachFeature(feature , layer) {
  // 'this' will now refer to your component's context
  let that = this;

  layer.on('click', <LeafletMouseEvent> (e) => {
      that.fitBounds = [
          [0.712, -74.227],
          [0.774, -74.125]
      ];

      // Aliased 'that' to refer to 'this' so it is in scope
      that.changeDetector.detectChanges();
  });

}

The let that = this trick is to make sure you don't have the same problem on the click event handler. But, you could also make that handler be a function in your class and use bind to set this.

ghybs
  • 47,565
  • 6
  • 74
  • 99
reblace
  • 4,115
  • 16
  • 16
  • 1
    Thanks for you fast and my problem solving answer :) – TheSorm Feb 18 '18 at 17:44
  • @reblace how would one go about nesting ngx-leaflet click events? I've used the above example to successfully click polygons to reveal the associated points that lie within that polygon. I want to then be able to click individual points to reveal a deeper level of points. How would I use `this` to differentiate between the two layers? – Lauren May 23 '18 at 20:35
  • @lauren To click individual points that are overlapping with polygons will probably involve CSS (e.g., pointer-events) and possibly deliberate layer ordering. As for differentiating, you could break them into separate geoJSON layers and have different onEachFeature properties for each. – reblace May 25 '18 at 18:35
  • @reblace You saved ma a lot of time with ".bind(this)" solution. The next problem that I have is layer.on('click', event is not firing when I click on it in the map.. Do you know maybe what can be a problem for that? layer.on('click', (e) => {e.target.setStyle({fillColor :'red'})}); I'm using Angular 11 – Dan Aug 18 '21 at 12:09