ngx-leaflet 不通过服务检测图层更改 (Angular 6)
ngx-leaflet does not detect layer changes through a service (Angular 6)
我是 运行 Angular 6,我想动态地向传单地图添加一个图层,但是如果图层是从另一个组件修改的,我无法检测到 leafletLayers 的变化。如果从 map.component
执行图层更改,一切正常,但如果我从外部进行更改,则它不起作用:
示例:
map.component.ts
layers: Layer[];
addPolygon () {
this.layers = [polygon([[ 43, 3 ], [ 42, 0 ], [ 44, 1 ]])]
}
map.component.html
<div class="map"
leaflet
(leafletMapReady)="onMapReady($event)"
[leafletOptions]="options"
[leafletLayers]="layers">
</div>
<div>
<button type="button" name="button" (click)="addPolygon()"></button>
</div>
现在一切正常,只要单击按钮,多边形就会显示出来。但是我需要那个按钮在另一个组件中(form.component.ts
),所以我尝试与服务共享 addPolygon()
功能:
server.service.ts
@Injectable()
export class ServerService {
addPolygon: Function;
}
我修改了MapComponent
并添加了调用服务的构造函数
map.component.ts
export class MapComponent{
layers: Layer[];
constructor(private serverService: ServerService){
this.serverService.addPolygon = this.addPolygon
};
form.component.ts
export class FormComponent implements OnInit {
constructor(private serverService: ServerService) { }
triggerMap() {
this.serverService.addPolygon()
}
}
但是如果我在 form.component.html
中的按钮上绑定 triggerMap()
,则多边形不会添加到地图中。然而,控制台显示 map.component.ts
中的 addPolygon
已达到。
我什至尝试使用 NgZone
,但没有任何区别。有什么建议吗?
Angular CLI:6.0.8
我想我已经了解了您的具体问题。它并不是真正特定于 Angular 或 Leaflet。我认为它更像是 Typescript 和 Javascript 的产物(或者可能是特定于 AOT 编译和 TS->JS 转译工作方式的东西)。
基本上,我认为问题是当您将 addPolygon 函数分配给服务对象时,this
上下文发生了变化。因此,this
最终成为服务的 this
而不是组件 this
。结果是在我假设服务的内部创建了一个新的图层数组。您可以(某种程度上)通过在 MapComponent 中执行以下操作来确认这一点:
export class MapComponent {
layers: Layer[] = [];
counter = 0;
constructor(
private serverService: ServerService,
private zone: NgZone
) {
this.serverService.addPolygon = this.addPolygon;
}
options = {
layers: [
tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 18, attribution: '...' })
],
zoom: 5,
center: latLng(42, 2)
};
addPolygon () {
console.log('I am in addPolygon in MapComponent');
this.counter++;
console.log(`Here\'s the counter: ${this.counter}`);
this.layers = [
polygon( [[ 43, 3 ], [ 42, 0 ], [ 44, 1 ]] )
];
}
resetLayers () {
console.log('Resetting layers');
console.log(`Here\'s the counter: ${this.counter}`);
this.layers = [];
}
}
这里的想法是,我正在修改 addPolygon
内部的本地 counter
成员变量,然后将其打印到控制台。我还将它打印到 resetLayers
函数内部的控制台。
当我按以下顺序单击按钮时:MapComponent、Reset、FormComponent,我得到以下输出:
I am in addPolygon in MapComponent
map.component.ts:36 Here's the counter: 1
map.component.ts:44 Resetting layers
map.component.ts:45 Here's the counter: 1
map.component.ts:34 I am in addPolygon in MapComponent
map.component.ts:36 Here's the counter: NaN
MapComponent 单击将计数器从 0 递增到 1,并使用值 1 正确打印它。重置单击将打印正确的计数器值 1。但是,FormComponent 单击将打印 NaN,因为它未初始化为值,所以递增它就变成了 NaN。
为了确定此上下文用于 FormComponent 对 addPolygon 的调用,我为 AppComponent、ServerService 和 FormComponent 添加了初始化为不同值的计数器。事实证明,它使用来自 ServerService
.
的 this
上下文调用 addPolygon
因此,我认为您的问题的解决方案是将图层数组放在 ServerServicem 中,或者使用输出绑定将事件从 FormComponent 传递到作为 MapComponent 和 FormComponent 的父组件的组件。
我是 运行 Angular 6,我想动态地向传单地图添加一个图层,但是如果图层是从另一个组件修改的,我无法检测到 leafletLayers 的变化。如果从 map.component
执行图层更改,一切正常,但如果我从外部进行更改,则它不起作用:
示例:
map.component.ts
layers: Layer[];
addPolygon () {
this.layers = [polygon([[ 43, 3 ], [ 42, 0 ], [ 44, 1 ]])]
}
map.component.html
<div class="map"
leaflet
(leafletMapReady)="onMapReady($event)"
[leafletOptions]="options"
[leafletLayers]="layers">
</div>
<div>
<button type="button" name="button" (click)="addPolygon()"></button>
</div>
现在一切正常,只要单击按钮,多边形就会显示出来。但是我需要那个按钮在另一个组件中(form.component.ts
),所以我尝试与服务共享 addPolygon()
功能:
server.service.ts
@Injectable()
export class ServerService {
addPolygon: Function;
}
我修改了MapComponent
并添加了调用服务的构造函数
map.component.ts
export class MapComponent{
layers: Layer[];
constructor(private serverService: ServerService){
this.serverService.addPolygon = this.addPolygon
};
form.component.ts
export class FormComponent implements OnInit {
constructor(private serverService: ServerService) { }
triggerMap() {
this.serverService.addPolygon()
}
}
但是如果我在 form.component.html
中的按钮上绑定 triggerMap()
,则多边形不会添加到地图中。然而,控制台显示 map.component.ts
中的 addPolygon
已达到。
我什至尝试使用 NgZone
,但没有任何区别。有什么建议吗?
Angular CLI:6.0.8
我想我已经了解了您的具体问题。它并不是真正特定于 Angular 或 Leaflet。我认为它更像是 Typescript 和 Javascript 的产物(或者可能是特定于 AOT 编译和 TS->JS 转译工作方式的东西)。
基本上,我认为问题是当您将 addPolygon 函数分配给服务对象时,this
上下文发生了变化。因此,this
最终成为服务的 this
而不是组件 this
。结果是在我假设服务的内部创建了一个新的图层数组。您可以(某种程度上)通过在 MapComponent 中执行以下操作来确认这一点:
export class MapComponent {
layers: Layer[] = [];
counter = 0;
constructor(
private serverService: ServerService,
private zone: NgZone
) {
this.serverService.addPolygon = this.addPolygon;
}
options = {
layers: [
tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 18, attribution: '...' })
],
zoom: 5,
center: latLng(42, 2)
};
addPolygon () {
console.log('I am in addPolygon in MapComponent');
this.counter++;
console.log(`Here\'s the counter: ${this.counter}`);
this.layers = [
polygon( [[ 43, 3 ], [ 42, 0 ], [ 44, 1 ]] )
];
}
resetLayers () {
console.log('Resetting layers');
console.log(`Here\'s the counter: ${this.counter}`);
this.layers = [];
}
}
这里的想法是,我正在修改 addPolygon
内部的本地 counter
成员变量,然后将其打印到控制台。我还将它打印到 resetLayers
函数内部的控制台。
当我按以下顺序单击按钮时:MapComponent、Reset、FormComponent,我得到以下输出:
I am in addPolygon in MapComponent
map.component.ts:36 Here's the counter: 1
map.component.ts:44 Resetting layers
map.component.ts:45 Here's the counter: 1
map.component.ts:34 I am in addPolygon in MapComponent
map.component.ts:36 Here's the counter: NaN
MapComponent 单击将计数器从 0 递增到 1,并使用值 1 正确打印它。重置单击将打印正确的计数器值 1。但是,FormComponent 单击将打印 NaN,因为它未初始化为值,所以递增它就变成了 NaN。
为了确定此上下文用于 FormComponent 对 addPolygon 的调用,我为 AppComponent、ServerService 和 FormComponent 添加了初始化为不同值的计数器。事实证明,它使用来自 ServerService
.
this
上下文调用 addPolygon
因此,我认为您的问题的解决方案是将图层数组放在 ServerServicem 中,或者使用输出绑定将事件从 FormComponent 传递到作为 MapComponent 和 FormComponent 的父组件的组件。