在我使用Google Maps InfoWindow显示位置详细信息的项目中,我遇到了敲除绑定问题。我已经将所选位置的数据绑定到了InfoWindow的HTML内容,这似乎在开始时工作正常。
现在出现问题:只要InfoWindow关闭(例如按下x按钮),谷歌地图从DOM中完全删除html内容并再次添加,当InfoWindow是再次显示(例如,单击下一个标记时)。
这里的问题是,一旦元素从DOM中删除,绑定就会丢失,因此内容不再更新。
我知道如何重新应用绑定到这个确切的元素?调用ko.applyBindings()再次导致异常“你不能多次将绑定应用于同一个元素”。
这里是InfoWindow内容的HTML元素:
<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初始化函数和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);
}
}
答案 0 :(得分:1)
我想我会为我使用的这个问题添加另一个解决方案。
您可以设置内容字符串(如Nurik所述)并让它保留您的绑定,但还有一些额外的步骤。然后,您需要使用jQuery将字符串转换为DOM节点并重新应用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);
)}
答案 1 :(得分:0)
感谢您的提问。它很难:)如果你查看infoWindow的google文档,它表明你需要告诉函数内容的来源:
而非写作:infoWindow = new google.maps.InfoWindow();
infoWindow.setContent(document.getElementById('info-content'));
infowindow = new google.maps.InfoWindow({
content: contentString
});
当然你还需要定义contentString。
请查看此处的文档:https://developers.google.com/maps/documentation/javascript/examples/infowindow-simple
答案 2 :(得分:0)
似乎我通过将内容包装在另一个不可见的容器div中并在InfoWindow关闭时将DOM元素重新添加到容器中来找到解决方案。
HTML现在看起来像这样:
<div id="info-window-container" style="display:none;">
<div id="info-content" data-bind="if:selectedPlace">
...
</div>
</div>
我将此行添加到init函数:
google.maps.event.addListener(infoWindow, 'closeclick', closeInfoWindow);
这个函数让JS重新将infoWindow内容添加到DOM:
function closeInfoWindow() {
document.getElementById('info-window-container').appendChild(infoWindow.getContent());
}
现在knockout按预期更新infoWindow内容,并在点击标记时正确显示。