Angular 4中AGM地图组件使用hidden与*ngIf的初始化问题
Hey there! Let's tackle this AGM + Angular 4 issue you're facing. I've run into similar conditional rendering headaches with map components before, so here's a breakdown of the problem and actionable fixes:
When you use *ngIf="useGoogleMap" and set it to false, Angular completely removes the AGM-related elements from the DOM. That means the AGM components never get a chance to initialize their internal Google Maps API hooks. Later, if you toggle useGoogleMap back to true, the AGM components might fail to properly bootstrap themselves—leading to broken autocomplete, unresponsive map interactions, or sync issues with your lat/lng inputs.
1. Use [hidden] Instead of *ngIf (Simplest Fix)
Unlike *ngIf, [hidden] only hides elements via CSS (setting display: none) instead of removing them from the DOM. This way, AGM components initialize normally on page load, and you just toggle visibility as needed.
Example template code:
<!-- Non-Google Map address input --> <input type="text" [hidden]="useGoogleMap" placeholder="Enter address without map" > <!-- AGM Autocomplete (hidden when useGoogleMap is false) --> <agm-autocomplete [hidden]="!useGoogleMap" (placeChanged)="onPlaceSelected($event)" > <input type="text" placeholder="Search address on map"> </agm-autocomplete> <!-- Editable lat/lng inputs --> <div> <label>Latitude:</label> <input type="number" [(ngModel)]="lat" (change)="updateMapMarker()"> </div> <div> <label>Longitude:</label> <input type="number" [(ngModel)]="lng" (change)="updateMapMarker()"> </div> <!-- AGM Map (only visible if useGoogleMap is true) --> <agm-map [hidden]="!useGoogleMap" [latitude]="lat" [longitude]="lng" (mapClick)="onMapClicked($event)" > <agm-marker [latitude]="lat" [longitude]="lng"></agm-marker> </agm-map>
Note: This keeps AGM components in the DOM at all times, which is fine for most use cases. If you're worried about performance with heavy map components, skip to the next solution.
2. Extract AGM Logic into a Child Component
If you prefer keeping unused components out of the DOM, split your AGM-related code into a dedicated child component. When useGoogleMap switches to true, Angular will create the child component from scratch, triggering its full initialization lifecycle (including AGM's API setup).
Parent Component Template
<input type="text" *ngIf="!useGoogleMap" placeholder="Enter address without map" > <agm-map-component *ngIf="useGoogleMap" [(lat)]="lat" [(lng)]="lng" ></agm-map-component> <!-- Lat/lng inputs can stay here or move to the child --> <div> <label>Latitude:</label> <input type="number" [(ngModel)]="lat"> </div> <div> <label>Longitude:</label> <input type="number" [(ngModel)]="lng"> </div>
Child Component (agm-map-component)
This component handles all AGM initialization, autocomplete, and map interactions. Its ngOnInit and ngAfterViewInit hooks will run every time the component is created, ensuring AGM sets up correctly.
3. Manually Trigger AGM Initialization (Advanced)
If you must stick with *ngIf, you can manually kick off AGM's initialization after toggling useGoogleMap to true. This requires accessing the AGM component instance and triggering its internal setup logic.
Example component code:
import { Component, ViewChild, OnInit } from '@angular/core'; import { AgmAutocomplete, AgmMap } from '@agm/core'; @Component({ selector: 'app-address-input', templateUrl: './address-input.component.html' }) export class AddressInputComponent implements OnInit { useGoogleMap = false; lat = 0; lng = 0; @ViewChild(AgmAutocomplete) autocomplete!: AgmAutocomplete; @ViewChild(AgmMap) map!: AgmMap; toggleGoogleMap() { this.useGoogleMap = !this.useGoogleMap; if (this.useGoogleMap) { // Add a small delay to ensure DOM has rendered the AGM elements setTimeout(() => { // Trigger autocomplete initialization (depends on AGM version) if (this.autocomplete && this.autocomplete.getPlace) { // Some AGM versions expose an init method, or you can re-bind the place change event this.autocomplete.ngAfterViewInit(); } // Refresh map if needed if (this.map && this.map._map) { google.maps.event.trigger(this.map._map, 'resize'); } }, 150); } } }
Caution: This relies on AGM's internal APIs, which might change between versions. Test thoroughly if you go this route.
Whichever solution you pick, make sure to sync your editable lat/lng inputs with the map:
- When a user selects an address via autocomplete, update
latandlng - When a user edits the lat/lng inputs, update the map marker position
- When a user clicks the map, update the lat/lng inputs
Example method for autocomplete place selection:
onPlaceSelected(place: google.maps.places.PlaceResult) { if (place.geometry?.location) { this.lat = place.geometry.location.lat(); this.lng = place.geometry.location.lng(); } }
内容的提问来源于stack exchange,提问作者Carolina

