【问题标题】:Binding KnockoutJS to Google Maps InfoWindow content将 KnockoutJS 绑定到 Google Maps InfoWindow 内容
【发布时间】:2015-08-12 16:39:05
【问题描述】:

在我使用 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);
    }
}

【问题讨论】:

    标签: javascript html google-maps knockout.js


    【解决方案1】:

    我想我会为我使用过的这个问题添加另一个解决方案。

    您可以设置内容字符串(如 Nurik 所述)并让它保留您的绑定,但还有几个额外的步骤。然后您需要使用 jQuery 将字符串转换为 DOM 节点并重新应用敲除绑定:

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

    【讨论】:

      【解决方案2】:

      看来我自己找到了一个解决方案,将内容包装在另一个不可见的容器 div 中,并在 InfoWindow 关闭时将 DOM 元素重新添加到容器中。

      HTML 现在看起来像这样:

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

      我在初始化函数中添加了这一行:

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

      这个函数给 JS 重新添加 infoWindow 内容到 DOM:

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

      现在敲除会按预期更新 infoWindow 内容,并在单击标记时正确显示。

      【讨论】:

        【解决方案3】:

        感谢您的提问。它很难:) 如果你查看 infoWindow 的谷歌文档,它表明你需要告诉函数内容来自哪里:

        而不是写: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

        【讨论】:

        • 这并不能解决我的问题。我想继续使用淘汰赛绑定,如果我手动构建字符串,那将不起作用。只要我不关闭 InfoWindow,我当前的解决方案就可以像绑定一样工作。例如在标记之间单击时,窗口会更改内容。
        猜你喜欢
        • 2021-10-20
        • 2011-05-16
        • 1970-01-01
        • 2013-09-17
        • 2010-12-13
        • 2015-07-09
        • 2021-01-15
        • 2013-01-18
        • 1970-01-01
        相关资源
        最近更新 更多