开放层 5 | Angular 7 | Angular Material |地图在 angular material mat-stepper 中不起作用
OpenLayers 5 | Angular 7 | Angular Material | Map is not working inside angular material mat-stepper
我在我的组件 ts 文件中导入了 OpenLayers 地图,然后我创建了一个 div 块,其 id = map 必须在其中显示 OpenLayers 地图,但它没有。当我将 div 块 (#map) 移到 mat-stepper 块之外时,它就起作用了。
Component.ts:
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import OlMap from 'ol/Map';
import OlXYZ from 'ol/source/XYZ';
import OlTileLayer from 'ol/layer/Tile';
import OlView from 'ol/View';
import { fromLonLat } from 'ol/proj';
@Component({
selector: 'app-sell',
templateUrl: './sell.component.html',
styleUrls: ['./sell.component.scss'],
})
export class SellComponent implements OnInit {
...
map: OlMap;
source: OlXYZ;
layer: OlTileLayer;
view: OlView;
...
ngOnInit() {
this.source = new OlXYZ({
url: 'http://tile.osm.org/{z}/{x}/{y}.png',
});
this.layer = new OlTileLayer({
source: this.source,
});
this.view = new OlView({
center: fromLonLat([6.661594, 50.433237]),
zoom: 3,
});
this.map = new OlMap({
target: 'map',
layers: [this.layer],
view: this.view,
});
}
Component.html:
<mat-horizontal-stepper
linear
labelPosition="bottom"
#stepper
class="sell-form-container"
>
<mat-step ...>
<form ...>
...
<div id="map"></div> //<- here it does not work, map does not display
...
</form>
</mat-step>
...
</mat-horizontal-stepper>
<div id="map"></div> //<- here it works, map displays
Component.css:
#map {
width: 100%;
height: 500px;
}
我的代码有什么问题?
我认为您的问题与您尝试将 OLMap 附加到 mat-stepper 或 mat-step 的嵌入内容中的内容有关。
在组件生命周期中,子组件在父组件的 OnInit 阶段没有准备好。因为您将需要的 div 放在 mat 组件中,所以它被包含在该组件的生命周期中。
解决此问题的一种方法是使用 ngAfterViewInit 生命周期方法。在该方法中使用您的代码应该可以解决此问题。
ngAfterViewInit() {
this.map = new OlMap({
target: 'map',
layers: [this.layer],
view: this.view,
});
}
出于潜在的好奇心,我还想介绍另一种使用组件的方法。留意嵌入的内容,如果你想要的元素在当前组件中,你应该使用 ViewChild 装饰器 select 它。否则,如果它在子组件中,请使用 ContentChild 装饰器。
// html
<mat-horizontal-stepper ...>
<mat-step ...>
<form ...>
...
<div #myMapRef id="map"></div>
...
</form>
</mat-step>
...
</mat-horizontal-stepper>
// parent ts
@ContentChild('myMapRef') // <-- if it's in a child component, your case should use this
@ViewChild('myMapRef') // <-- if it's in this component, your "this is working" would use this
myMap: ElementRef;
ngAfterViewInit() {
console.log(this.myMap); // can get the ID from the ElementRef
}
我强烈建议您实际熟悉组件生命周期的深度。这是我希望早点在学习时做的一件事 Angular。
我在我的组件 ts 文件中导入了 OpenLayers 地图,然后我创建了一个 div 块,其 id = map 必须在其中显示 OpenLayers 地图,但它没有。当我将 div 块 (#map) 移到 mat-stepper 块之外时,它就起作用了。
Component.ts:
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import OlMap from 'ol/Map';
import OlXYZ from 'ol/source/XYZ';
import OlTileLayer from 'ol/layer/Tile';
import OlView from 'ol/View';
import { fromLonLat } from 'ol/proj';
@Component({
selector: 'app-sell',
templateUrl: './sell.component.html',
styleUrls: ['./sell.component.scss'],
})
export class SellComponent implements OnInit {
...
map: OlMap;
source: OlXYZ;
layer: OlTileLayer;
view: OlView;
...
ngOnInit() {
this.source = new OlXYZ({
url: 'http://tile.osm.org/{z}/{x}/{y}.png',
});
this.layer = new OlTileLayer({
source: this.source,
});
this.view = new OlView({
center: fromLonLat([6.661594, 50.433237]),
zoom: 3,
});
this.map = new OlMap({
target: 'map',
layers: [this.layer],
view: this.view,
});
}
Component.html:
<mat-horizontal-stepper
linear
labelPosition="bottom"
#stepper
class="sell-form-container"
>
<mat-step ...>
<form ...>
...
<div id="map"></div> //<- here it does not work, map does not display
...
</form>
</mat-step>
...
</mat-horizontal-stepper>
<div id="map"></div> //<- here it works, map displays
Component.css:
#map {
width: 100%;
height: 500px;
}
我的代码有什么问题?
我认为您的问题与您尝试将 OLMap 附加到 mat-stepper 或 mat-step 的嵌入内容中的内容有关。
在组件生命周期中,子组件在父组件的 OnInit 阶段没有准备好。因为您将需要的 div 放在 mat 组件中,所以它被包含在该组件的生命周期中。
解决此问题的一种方法是使用 ngAfterViewInit 生命周期方法。在该方法中使用您的代码应该可以解决此问题。
ngAfterViewInit() {
this.map = new OlMap({
target: 'map',
layers: [this.layer],
view: this.view,
});
}
出于潜在的好奇心,我还想介绍另一种使用组件的方法。留意嵌入的内容,如果你想要的元素在当前组件中,你应该使用 ViewChild 装饰器 select 它。否则,如果它在子组件中,请使用 ContentChild 装饰器。
// html
<mat-horizontal-stepper ...>
<mat-step ...>
<form ...>
...
<div #myMapRef id="map"></div>
...
</form>
</mat-step>
...
</mat-horizontal-stepper>
// parent ts
@ContentChild('myMapRef') // <-- if it's in a child component, your case should use this
@ViewChild('myMapRef') // <-- if it's in this component, your "this is working" would use this
myMap: ElementRef;
ngAfterViewInit() {
console.log(this.myMap); // can get the ID from the ElementRef
}
我强烈建议您实际熟悉组件生命周期的深度。这是我希望早点在学习时做的一件事 Angular。