Angular14 google-map点击事件传MapMarker报TS2345错误如何解决
Angular Google Maps Marker点击触发InfoWindow类型错误修复方案
问题现象
在Angular 14项目中使用@angular/google-maps实现点击地图标记弹出信息窗口功能时,编译阶段抛出TS类型错误:
error TS2345: Argument of type 'HTMLElement' is not assignable to parameter of type 'MapMarker'
错误定位在模板中标记点击事件绑定位置(mapClick)="openInfo(markerElem, s.Nome)",传入的markerElem是原生DOM元素类型,不符合方法要求的MapMarker组件实例类型。
原有问题代码
HTML模板
<google-map #GoogleMap height="500px" width="100%" [zoom]="zoom" [center]="center" [options]="options"> <map-marker-clusterer [imagePath]="'./assets/images/mappa/m'"> <map-marker #markerElem *ngFor="let s of strutture; let i = index;" (mapClick)="openInfo(markerElem, s.Nome)" [position]="{lat: toNumber(s.Latitudine), lng: toNumber(s.Longitudine)}" [label]="getLabel(s.Prezzo.toString())" [icon]="getIcon()"> </map-marker> <map-info-window>{{ infoContent }}</map-info-window> </map-marker-clusterer>
TS组件逻辑
export class MappaRisultatiComponent implements OnInit { @Input() strutture: Struttura[]; toNumber = toNumber; center!: google.maps.LatLngLiteral; icon: google.maps.Icon; zoom: 8; options: google.maps.MapOptions = { // 地图配置项省略 } @ViewChild(GoogleMap, { static: false }) map: GoogleMap @ViewChild(MapInfoWindow, { static: false }) info: MapInfoWindow infoContent = '' openInfo(marker: MapMarker, content) { this.infoContent = content this.info.open(marker) } ngOnInit() { this.center = { lat: toNumber(this.strutture[0].Latitudine), lng: toNumber(this.strutture[0].Longitudine), } this.icon = { url: './assets/images/mappa/priceLabel.png' } } public getLabel(prezzo: string): google.maps.MarkerLabel { let ret: google.maps.MarkerLabel = { fontWeight: 'bold', text: prezzo + '€' } return ret; } public getIcon(): google.maps.Icon { let ret: google.maps.Icon = { url: './assets/images/mappa/priceLabel.png' } return ret; }
修复方案
优先推荐:显式指定模板变量读取组件实例
Angular中默认的模板变量#varName获取的是原生DOM元素引用,要获取组件实例需要匹配组件的exportAs标识,MapMarker组件的导出标识为mapMarker,只需要修改模板中标记的模板变量声明即可,TS逻辑不需要任何改动:
<!-- 仅修改#markerElem为#markerElem="mapMarker" --> <map-marker #markerElem="mapMarker" *ngFor="let s of strutture; let i = index;" (mapClick)="openInfo(markerElem, s.Nome)" [position]="{lat: toNumber(s.Latitudine), lng: toNumber(s.Longitudine)}" [label]="getLabel(s.Prezzo.toString())" [icon]="getIcon()"> </map-marker>
修改后markerElem变量会直接持有MapMarker组件实例,类型完全匹配,编译错误直接消除,点击标记即可正常弹出信息窗口。
备选方案:通过点击事件参数获取Marker实例
map-marker的mapClick事件会自带当前触发事件的标记实例参数,可以直接使用$event传参,不需要自定义模板变量:
- 修改模板事件绑定:
<map-marker *ngFor="let s of strutture; let i = index;" (mapClick)="openInfo($event, s.Nome)" [position]="{lat: toNumber(s.Latitudine), lng: toNumber(s.Longitudine)}" [label]="getLabel(s.Prezzo.toString())" [icon]="getIcon()"> </map-marker> - 调整TS方法兼容不同版本的事件返回格式:
openInfo(marker: MapMarker | google.maps.MapMouseEvent, content) { const targetMarker = marker instanceof MapMarker ? marker : (marker as any).marker as MapMarker this.infoContent = content this.info.open(targetMarker) }
注意:不同版本的@angular/google-maps事件返回格式有差异,部分版本直接返回MapMarker实例,部分版本返回鼠标事件对象、标记实例挂载在marker属性上,第一种方案兼容性更好,优先使用。
内容的提问来源于stack exchange,提问作者Federico Pisa
相关产品推荐
相关产品推荐

