属性 绑定地图点击事件与 select 输入 ngx-leaflet/Angular 2

Property binding map click event with dropdown select input in ngx-leaflet/Angular 2

我有一张带有区域多边形的地图。在地图下方,我有一个下拉 select 输入,可动态读取多边形名称作为选项。当用户单击地图上的区域多边形时,我希望下拉列表 select 输入更新为 selected 多边形名称(它作为 geojson 文件中的 'name' 字段存在)。

我认为实现此目的的方法是在 HTML 模板文件中使用 属性 绑定。所以在我的 select class 中,我将值 属性 设置为值 clicked,像这样:

<select class="form-control" id="selectRegion" [value]="clicked">

clicked 最初在应用程序组件中定义为空字符串。单击多边形时,我将 clicked 设置为 onEachFeature 单击事件中的多边形名称字段。控制台日志显示 clicked 变量正在正确更新。但是,select 输入不会按预期随点击事件更新。

我怀疑问题是 this 没有在我的函数中正确更新?如何让 select 输入与我的地图点击事件一起更新?

这是一些代码(基于来自 Asymmetrik 的 ngx-leaflet-tutorial-ngcli):

Geojson(在assets文件夹中另存为polygons.geojson

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "stroke": "#555555",
        "stroke-width": 2,
        "stroke-opacity": 1,
        "fill": "#555555",
        "fill-opacity": 0.5,
        "name": "poly1"
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              -121.95098876953125,
              46.82966386051541
            ],
            [
              -121.78482055664061,
              46.82966386051541
            ],
            [
              -121.78482055664061,
              46.91368905872705
            ],
            [
              -121.95098876953125,
              46.91368905872705
            ],
            [
              -121.95098876953125,
              46.82966386051541
            ]
          ]
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "stroke": "#555555",
        "stroke-width": 2,
        "stroke-opacity": 1,
        "fill": "#555555",
        "fill-opacity": 0.5,
        "name": "poly2"
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              -121.77726745605469,
              46.83107318799318
            ],
            [
              -121.62963867187499,
              46.83107318799318
            ],
            [
              -121.62963867187499,
              46.913220009605624
            ],
            [
              -121.77726745605469,
              46.913220009605624
            ],
            [
              -121.77726745605469,
              46.83107318799318
            ]
          ]
        ]
      }
    }
  ]
}

App.module.ts:

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


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

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

App.component.html:

<div class="map"
  leaflet
  [leafletLayers]="layers"
     [leafletFitBounds]="fitBounds"></div>
<div class="form-group">
  <select class="form-control" id="selectRegion" [value] = "clicked">
    <option *ngFor="let region of regions">{{ region }}</option>
  </select>
</div>

App.component.ts:

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';

import * as L from 'leaflet';

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

  layers: L.Layer[];
  fitBounds = [[46.67, -122.25], [47.01, -121.302]];
  regions = [];
  clicked = '';

  constructor(private http: HttpClient) { }

  ngOnInit() {

    // read in geojson of poly
    this.http.get<any>('/assets/polygons.geojson')
      .subscribe(poly => {

        const tileLayer = L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_nolabels/{z}/{x}/{y}.png', {
          subdomains: 'abcd',
          maxZoom: 19
        });

        const polyLayer = L.geoJSON(poly, {
          onEachFeature: this.onEachFeature.bind(this)
        });

        this.layers = [ tileLayer, polyLayer ];
        console.log(this);
      });
  }

  // loop through each feature of polyLayer
  onEachFeature(feature, layer) {

    // push polygon names to regions array
    this.regions.push(feature.properties.name);

    layer.on('click', <LeafletMouseEvent> (e) => {
      this.clicked = e.target.feature.properties.name;
      console.log(this.clicked);
    });
  }
}

onEachFeature 函数和 layer.on('click'... 事件回调可能在 Angular 区域之外被调用。如果是这种情况,则更改检测不会自动工作。您应该将更改包装在 zone.run() 调用中,以确保您的更改是在 Angular 区域中进行的 - 如本例所示:

// loop through each feature of polyLayer
onEachFeature(feature, layer) {

  this.zone.run(() => {
    // push polygon names to regions array
    this.regions.push(feature.properties.name);

    layer.on('click', <LeafletMouseEvent> (e) => {
      this.zone.run(() => {
        this.clicked = e.target.feature.properties.name;
        console.log(this.clicked);
      }
    });
  }

}

您可以按照这些说明 (https://github.com/Asymmetrik/ngx-leaflet#a-note-about-change-detection) 了解其工作原理并将 ngZone 实例注入您的组件。