In a project where I'm using the Google Maps InfoWindow to display details for locations, I have run into problems with knockout binding. I've bound the data of the selected location with knockout the HTML content of the InfoWindow, which seems to work fine in the beginning.
Now the problem: as soon as the InfoWindow is closed (e.g. by pressing the x-button), google maps removes the html content completely from the DOM and adds it again, when the InfoWindow is displayed again (e.g. when the next marker is clicked).
The problem here is, that the binding gets lost as soon as the element is removed from the DOM, so the content doesn't update anymore.
Any idea how i can reapply the binding to this exact element? calling ko.applyBindings() again leads to the exception "You cannot apply bindings multiple times to the same element".
Here the HTML element for the InfoWindow content:
<div id="info-content" data-bind="if:selectedPlace">
<div class="gm-iw gm-sm" data-bind="with:selectedPlace">
<div class="gm-title" data-bind="text:name"></div>
<div class="gm-basicinfo">
<div class="gm-addr" data-bind="text:vicinity"></div>
<div class="gm-website" data-bind="if:website"><a target="_blank" data-bind="attr: {href:website}, text:websiteText"></a></div>
<div class="gm-phone" data-bind="text:formatted_phone_number"></div>
</div>
<div class="gm-rev" >
<span data-bind="if:rating">
<span class="gm-numeric-rev" data-bind="text:rating"></span>
<div class="gm-stars-b">
<div class="gm-stars-f" data-bind="style: { width: getStarWidth } "></div>
</div>
</span>
<span data-bind="if:url"><a target="_blank" data-bind="attr: {href:url}">see more</a></span>
</div>
</div>
JS initialize function and onClick function:
// the initialize function gets called after ko.applyBindings(model)
ViewModel.prototype.initialize = function () {
... code to initialize map and search elements
// instantiate an InfoWindow
infoWindow = new google.maps.InfoWindow();
infoWindow.setContent(document.getElementById('info-content'));
...
}
// gets called for each place returned by the search,
// koPlace is the knockout observable for a place returned by the search,
// i is the index of the search result
function addMarker(koPlace, i) {
// create a marker
var m = new google.maps.Marker({
title: koPlace.name(),
position: koPlace.jsPlace.geometry.location,
animation: google.maps.Animation.DROP,
});
m.koPlace = koPlace;
koPlace.marker = m;
markers[i] = m;
google.maps.event.addListener(m, 'click', markerClicked);
setTimeout(dropMarker(i), i * 100);
}
function markerClicked() {
var koPlace = this.koPlace; // this refers to the marker object
if (koPlace) { // just checking
koPlace.selected(true); // this is used for highlighting.
model.selectedPlace(koPlace); // this should set the binding.
infoWindow.open(map, this);
}
}