javascript html google-maps knockout.js

javascript - Enlace KnockoutJS a Google Maps InfoWindow contenido



html google-maps (3)

En un proyecto en el que estoy usando Google Maps InfoWindow para mostrar detalles de las ubicaciones, he tenido problemas con el enlace de nocaut. He vinculado los datos de la ubicación seleccionada con el contenido HTML de InfoWindow, lo que parece funcionar bien al principio.

Ahora el problema: tan pronto como se cierra la ventana de información (por ejemplo, presionando el botón x), google maps elimina completamente el contenido html del DOM y lo vuelve a agregar cuando se vuelve a mostrar InfoWindow (por ejemplo, cuando se hace clic en el siguiente marcador) )

El problema aquí es que el enlace se pierde tan pronto como el elemento se elimina del DOM, por lo que el contenido ya no se actualiza.

¿Alguna idea de cómo puedo volver a aplicar el enlace a este elemento exacto? llamar a ko.applyBindings () nuevamente conduce a la excepción "No se pueden aplicar enlaces varias veces al mismo elemento".

Aquí el elemento HTML para el contenido de InfoWindow:

<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>

Función de inicialización JS y función onClick:

// 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); } }


Gracias por la pregunta. Es difícil :) Si miras la documentación de google para la ventana de información, muestra que necesitas decirle a la función de dónde viene el contenido:

en lugar de escribir: infoWindow = new google.maps.InfoWindow(); infoWindow.setContent(document.getElementById(''info-content'')); infoWindow = new google.maps.InfoWindow(); infoWindow.setContent(document.getElementById(''info-content''));

podrías considerar esto:

infowindow = new google.maps.InfoWindow({ content: contentString });

por supuesto, también necesitaría definir contentString.

Consulte la documentación aquí: https://developers.google.com/maps/documentation/javascript/examples/infowindow-simple


Parece que encontré una solución al envolver el contenido en otro contenedor invisible div y volver a agregar el elemento DOM al contenedor cuando se cierre InfoWindow.

El HTML ahora se ve así:

<div id="info-window-container" style="display:none;"> <div id="info-content" data-bind="if:selectedPlace"> ... </div> </div>

Agregué esta línea a la función init:

google.maps.event.addListener(infoWindow, ''closeclick'', closeInfoWindow);

y esta función al JS para volver a agregar el contenido de InfoWindow al DOM:

function closeInfoWindow() { document.getElementById(''info-window-container'').appendChild(infoWindow.getContent()); }

ahora knockout actualiza el contenido de InfoWindow como se esperaba y se muestra correctamente cuando se hace clic en un marcador.


Pensé en agregar otra solución a este problema que he usado.

Puedes establecer la cadena de contenido (como dijo Nurik) y hacer que mantenga tus enlaces, pero hay un par de pasos adicionales. Luego necesita usar jQuery para convertir la cadena en un nodo DOM y volver a aplicar los enlaces knockout:

function makeContent() { var html = ''<div id="info-window-container" style="display:none;">'' + ''<div id="info-content" data-bind="if:selectedPlace">'' + ''...'' + ''</div>'' + ''</div>''; html = $parseHTML(html)[0]; return html; )} function addMarker() { var infoWindow = new google.maps.InfoWindow(); var m = new google.maps.Marker({ title: koPlace.name(), ... content: makeContent() }); m.koPlace = koPlace; koPlace.marker = m; markers[i] = m; google.maps.event.addListener(m, ''click'', function() { infoWindow.setContent(this.content); infoWindow.open(map,this); )}; ko.applyBindings(YourViewModel, m.content); )}