Knockoutjs google maps绑定Ajax调用

时间:2017-07-06 11:06:04

标签: javascript google-maps google-maps-api-3 knockout.js

我已经对这段代码进行了广泛的阅读和修补,但似乎无法让自己在谷歌地图上应用淘汰赛。如果我走在正确的轨道上,请告诉我。我正在使用一些默认标记(按预期工作)渲染地图,然后想要使用从选择表单上的on change事件触发的ajax调用派生的点来更新它们。有可能我缺少一些非常基本的东西,因为这是我第一次使用谷歌地图和KO而不太确定将V和VM分开的位置

my HTML 

    // html form with select option in jinja2
    <form action=""> 
    <select name="categories" onchange="showCategory(this.value)">
    <option value="">Select Category</option>
    {% for c in cat %}
    <option value={{c.id}}>{{c.name}}</option>
    {% endfor %}
    </select>
    </form>

//a div to display XMLHttpRequest response to make sure am getting that part right
        <div id="demo">
    <h1>The XMLHttpRequest Object</h1>
    </div>
 //the map div   
    <div id="map"></div>
        <script>

我的变量加上XMLHttpRequest

//Declare Map variable and markers array
      var map;
      var marker;
      var markers = [];
      var lat = -1.2886009200028272;
      var lng = 36.822824478149414;

      var features = [
          {
            name: name,
            position: {lat:lat, lng: lng},
            type: 'parking'
          },
          {
            name: name,
            position: {lat:-1.287785734541792, lng: 36.82161211967468},
            type: 'info'
          }
        ];

      // make XMLHttpRequest and update the above variables
      function showCategory(cat_id) {
      var xhttp;    
      if (cat_id == "") {
      document.getElementById("demo").innerHTML = "Please select a Category";
      return;
      }
      xhttp = new XMLHttpRequest();
      xhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
      var my_text = this.responseText;
      obj = JSON.parse(my_text);
      raw_lat = obj.Addresses[0].lat
      lat = parseFloat(raw_lat)
      raw_lng = obj.Addresses[0].lng
      lng = parseFloat(raw_lng)
      features = [
          {
            position: {lat:lat, lng: lng},
            type: 'info'
          },
          {
            name: name,
            position: {lat:-1.287785734541792, lng: 36.82161211967468},
            type: 'parking'
          }
        ];

      //check to confirm am getting a response
      document.getElementById("demo").innerHTML =
      this.responseText;

    }
    };

    xhttp.open("GET", "/loc/"+cat_id, true);
    xhttp.send();
    };

    //Fetch relevant map icons from Google

      var iconBase = 'https://maps.google.com/mapfiles/kml/shapes/';
        var icons = {
          parking: {
            icon: iconBase + 'parking_lot_maps.png'
          },
          library: {
            icon: iconBase + 'library_maps.png'
          },
          info: {
            icon: iconBase + 'info-i_maps.png'
          }
        };

地图代码

//create the map and the view model   
      function initMap() {
        var ViewModel = function() {
          var self = this
          self.lat = ko.observable(lat)
          self.lng = ko.observable(lng)
        self.map = new google.maps.Map(document.getElementById("map"), {
          zoom: 16,
          center: new google.maps.LatLng(self.lat(), self.lng()),
          mapTypeId: 'roadmap'
        });


       self.updatedfeatures = ko.observableArray(features.slice());
        // Create markers.
        self.updatedfeatures().forEach(function(feature) {
            marker = new google.maps.Marker({
            position: feature.position,
            icon: icons[feature.type].icon,
            map: self.map
          });
          markers.push(marker);
        });
      };
      ko.applyBindings(new ViewModel());
      };

1 个答案:

答案 0 :(得分:0)

为此目的,结果证明这是一种矫枉过正。要点是XMLHttpRequest是异步的,并且ajax调用将设置lat和lng值,但是在其余的javascript运行之后。当然,在KO中有js和延期更新的承诺,但我意识到有一种更容易的方法来完成同样的事情。我只是将XMLHttpRequest函数移动到map函数中,并在选择值更改时使用document.getElementById("myId").addEventListener("change", myFunction);生成ajax请求,然后更新标记。我不需要KO,但当然它会派上用场,因为我在电话会议后进一步对制造商进行分类

所以这是我改变的代码部分

//create the map and the view model   
      function initMap() {
        var ViewModel = function() {
          var self = this
          self.lat = ko.observable(lat)
          self.lng = ko.observable(lng)

        self.lng.subscribe(function(newValue) {
        alert("new values are " + newValue);
        });

        self.map = new google.maps.Map(document.getElementById("map"), {
          zoom: 16,
          center: new google.maps.LatLng(self.lat(), self.lng()),
          mapTypeId: 'roadmap'
        });


       self.updatedfeatures = ko.observableArray(features);
        // Create markers.
        self.updatedfeatures().forEach(function(feature) {
            self.marker = new google.maps.Marker({
            position: feature.position,
            icon: icons[feature.type].icon,
            map: self.map
          });
          markers.push(self.marker);
        });

        document.getElementById("my_cats").addEventListener("change", myFunction);
        function myFunction() {
      var cat_id = document.getElementById("my_cats").value;
      var xhttp;
      xhttp = new XMLHttpRequest();
      xhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
      var my_text = this.responseText;
      obj = JSON.parse(my_text);
      var raw_lat = obj.Addresses[0].lat;
      lat = parseFloat(raw_lat);
      var raw_lng = obj.Addresses[0].lng;
      lng = parseFloat(raw_lng);
      features = [
          {
            position: {lat:lat, lng: lng},
            type: 'parking'
          },
          {
            name: name,
            position: {lat:-1.287785734541792, lng: 36.82161211967468},
            type: 'parking'
          }
        ];
      features.forEach(function(feature) {
            marker = new google.maps.Marker({
            position: feature.position,
            icon: icons[feature.type].icon,
            map: self.map
          });
          markers.push(marker);
        });

    }
    };

    xhttp.open("GET", "/loc/1", true);
    xhttp.send();
      }


      };
      ko.applyBindings(new ViewModel());

      };