I use google maps javascript api and I have to display an Angular component into the InfoWindow.
In my project I load the google map api with the Jsonp
service. Than I have the google.maps.Map
object available. Later in a component I create some markers and attach to them a click listener :
TypeScript :
let marker = new google.maps.Marker(opts);
marker.setValues({placeId: item[0]});
marker.addListener('click', (ev: google.maps.MouseEvent) => this.onMarkerClick(marker, ev));
And then in the click
handler I want to open an Info Window that contains an Angular Component:
TypeScript :
private onMarkerClick(marker: google.maps.Marker, ev: google.maps.MouseEvent) {
var div = document.createElement();
this.placeInfoWindow.setContent(div);
// Magic should happen here somehow
// this.placeInfoWindow.setContent('<app-info-view-element></app-info-view-element>');
this.placeInfoWindow.open(this.map, marker);
}
What I ended up doing was some vanilla JS:
TypeScript :
private onMarkerClick(marker: google.maps.Marker, ev: google.maps.MouseEvent) {
let div = document.createElement('div');
div.className = 'map-info-window-container';
div.style.height = '140px';
div.style.width = '240px';
this.placeInfoWindow.setContent(div);
this.placeInfoWindow.open(this.map, marker);
this.placesService.getPlace(marker.get('id')).subscribe(res => {
this.decorateInfoWindow(div, res.name, marker);
}, error => {
this.decorateInfoWindow(div, ':( Failed to load details: ', marker);
});
}
private decorateInfoWindow(containerEl: HTMLElement, title?:string, marker?:google.maps.Marker) {
let h3 = document.createElement('h3');
h3.innerText = title;
containerEl.appendChild(h3);
let buttonBar = document.createElement('div');
let editButton = document.createElement('button')
editButton.innerText = "Edit";
editButton.addEventListener('click', ev => {
this.editPlace(marker);
});
buttonBar.appendChild(editButton);
containerEl.appendChild(buttonBar);
}
The problem, as I learned, Is that the only viable way to create dynamic components is to use Angulars ViewContainerRef
:
But there are no docs or examples, describing how to create a ViewContainerRef
from a dynamically created element.
Is it posible to force the framework to process the DOM in some way ? As it is in a lot of threads is stated : "Angular does not process innerHTML
or appendChild
". Is this a complete dead end ?
Second: Is it possible using a Renderer
implementation ? (Not Familiar with it), I saw this Canvas Renderer Experiment and theoretically, I guess it would work also with the Google map, since we can extrapolate that the map is just a special kind of canvas. Is it still available in the last release or it changed ? DomRenderer
is not in the docs, however one can find it in the sources.