I have a component which visualize some data in an mat accordion, next to it is a google map which shows the location of each data point. On top of the component I have a dropdown, depending on the selection project data is refreshed and the accordion + map should update.
The map is its own component and data is shared via a service. I don't want to show the map when there is no data to visualize. I would like to work with [hidden] instead of ngIf because I dont need a new map instance in that case.
My current problem is that when the map is in a hidden state, then I change the drop down selection, project data gets updated and I have actual data, map is visible again, markers are shown but the map is fully zoomed out with with grey borders on the top and the bottom.
I can get it to work with ngIf and ChangeDetectorRef which probably is not best practice and I may have an error somewhere.
Template:
<div [hidden]="!projects || (projects && projects.length == 0)" class="right-panel" style="border-radius: 16px; overflow: hidden">
<app-map (markerClicked)="setExpandedPanel($event)"></app-map>
</div>
Map Component Template:
<div style="width: 100%; height: 100%; min-height: 750px">
<input id="pac-input" #placesContainer style="margin-top: 10px" type="text"/>
<google-map (mapInitialized)="onMapReady($event)" mapId="myMap" [zoom]="zoom" [center]="center"
width="100%" height="100%">
@for (marker of projectMarkers; track marker.position) {
<map-advanced-marker (mapClick)="onMarkerClick(marker.id)"
[position]="marker.position"
[content]="marker.icon"
[zIndex]="marker.zIndex"
/>
}
</google-map>
</div>
Map Component:
zoom: number = 7;
center: google.maps.LatLngLiteral = ..
projects: Project[] = [];
@Output() markerClicked = new EventEmitter<string | null>();
private mapReady$ = new BehaviorSubject<boolean>(false);
projectMarkers: CustomMapMarker[] = [];
currentExpandedProjectId: string | null = null;
markerSvgString = '<svg width="62" height="78" ..</g></svg>';
@ViewChild('placesContainer') placesElement!: ElementRef;
private map!: google.maps.Map;
constructor(
private projectStateService: ProjectStateService,
private mapService: MapBaseService,
private ref: ChangeDetectorRef
) {}
ngAfterViewInit(): void {
combineLatest([
this.projectStateService.projects$,
this.mapReady$
]).subscribe(([ projects, mapReady]) => {
if(mapReady && projects && projects.length > 0){
this.projects = projects!;
this.setProjectMarkers();
this.setBounds();
this.ref.detectChanges()
}
});
}
async onMapReady(map: google.maps.Map): Promise<void> {
await this.mapService.loadMapLibraries()
this.map = map;
this.map.setOptions({
gestureHandling: 'cooperative',
fullscreenControl: false,
mapTypeControl: true,
mapTypeControlOptions: {
style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR,
position: google.maps.ControlPosition.TOP_RIGHT
}
});
await this.mapService.initPlacesSearch(map, this.placesElement);
this.mapReady$.next(true);
}
Just switching between drop down selections with different projects works perfectly, its all about the switch of no projects > hidden map to projects > visible map.