列表没有在KnockOut JS中更新

时间:2017-12-11 20:06:58

标签: javascript google-maps knockout.js

我正在使用KnockOut JS和google maps api。创建了单页Web应用程序,用户可以通过该应用程序过滤地点的名称,并在地图上更新标记。 HTML代码。

<head>
    <title>Google maps</title>
    <link rel=stylesheet type=text/css href='css/style.css'>
</head>
<body>
    <div class="container">
        <div class="options-box">
            <h1>Liverpool Pubs and Bars - Anfield</h1>
            <hr>
            <div>
                <input data-bind='value: userInput' id="filter-area" type="text" placeholder="Enter your favorite Pub">
                <input data-bind='click: searchedPlace' id="filter-button" type='button' value="Filter">
            </div>
            <hr>
            <div>
                <ul data-bind='foreach: allPlaces'>
                    <div class="pubs" data-bind='text: name, click: $parent.setCurrentPlace'></div>
                </ul>
            </div>
        </div>
        <div id='map'></div>
    </div>
    <script src="https://maps.googleapis.com/maps/api/js?libraries=places,geometry,drawing&key=AIzaSyAJZiVbDVmFXz8_kPBjfugqCj68BPAKE88&callback=initMap"
async defer></script>
    <script type="text/javascript" src="js/knockout-3.2.0.js"></script>
    <script type="text/javascript" src="js/app.js"></script>
</body>

JS代码:

var ViewModel = function (googleMap, myPlaces, infoWindow, bounds) {

    var self = this;

    this.map = googleMap;
    this.allPlaces = ko.observableArray([]);
    this.markers = [];
    var geocoder = new google.maps.Geocoder();
    myPlaces.forEach(function(place) {
        var newObj = new Place(place);
        var title = newObj.name;

        // Getting the geocode for the place.
        geocoder.geocode({ 'address': place.address }, function(results, status) {
            if (status == google.maps.GeocoderStatus.OK) {
                marker = new google.maps.Marker({
                    map: self.map,
                    position: results[0].geometry.location,
                    animation: google.maps.Animation.DROP,
                    title: title,
                    address: newObj.address
                });

                self.markers.push(marker);

                (function (marker, title) {
                     google.maps.event.addListener(marker, 'click', function () {
                         populateinfoWindow(marker, infoWindow);
                     });
                 })(marker, title);

                 bounds.extend(marker.position);
            }
        });
        self.allPlaces.push(newObj);
    });

    // function to set the current place.
    this.clearAllMarkers = function() {
        console.log(self.markers.length);
        console.log('reaching here');
        for( var i = 0; i < self.markers.length; i++) {
            //debugger;
            // console.log(self.markers[i]);
            // Making all markers disappear
            self.markers[i].setVisible(false);
            //debugger;
        }
        //debugger;
    }

    this.setCurrentPlace = function(place) {
        //debugger;
        self.clearAllMarkers();
        for( var i = 0; i < self.markers.length; i++) {

            if (place.name == self.markers[i].title) {
                self.markers[i].setVisible(true);

                (function (marker, title) {
                     google.maps.event.addListener(marker, 'click', function () {
                         populateinfoWindow(marker, infoWindow);
                     });
                 })(marker, place.name);

                 bounds.extend(self.markers[i].position);
            }
        }
    }

    // filtering places
    self.userInput = ko.observable('');
    this.searchedPlace = function() {

        // clearing all markers.
        self.clearAllMarkers();
        var p = [];
        self.allPlaces = ko.observableArray([]);

        for (var i = 0; i < self.markers.length; i++) {

            // check if its a substring.
            if (self.markers[i].title.toLowerCase().indexOf(self.userInput().toLowerCase()) !== -1) {

                // Showing markers.
                self.allPlaces.push(new Place({name: self.markers[i].title, address: self.markers[i].address}));
                self.markers[i].setVisible(true);
            }
        }
    }
}

var Place = function(data) {
    this.name = data.name;
    this.address = data.address;
}

var createMap = function () {
    var map;

    // Constructor creates a new map - only center and zoom are required.
    // Centering map at Anfield.
    map = new google.maps.Map(document.getElementById('map'), {
        center: {lat: 53.4308294, lng: -2.96083},
        mapTypeControl: false,
        zoom: 15
    });

    return map;
}

function initMap() {
google.maps.event.addDomListener(window, 'load', function(){

    // list of my places.
    var myPlaces = [
    {
        name: 'The Albert',
        address: '185 Walton Breck Rd, Liverpool L4 0RE, UK'
    },
    {
        name: 'Arkles',
        address: '77 Anfield Rd, Liverpool L4 0TJ, UK'
    },
    {
        name: 'The Sandon',
        address: '178-182 Oakfield Rd, Liverpool L4 0UH, UK'
    },
    {
        name: 'The Park Pub',
        address: '216-218 Walton Breck Rd, Liverpool L4 0RQ, UK'
    },
    {
        name: 'The Twelfth Man',
        address: '121 Walton Breck Rd, Liverpool L4 0RD, UK'
    }
    ];
    var googleMap = createMap();
    var infoWindow = new google.maps.InfoWindow();
    var bounds = new google.maps.LatLngBounds();
    ko.applyBindings(new ViewModel(googleMap, myPlaces, infoWindow, bounds))
});
}

function populateinfoWindow(marker, infoWindow) {
    console.log(marker.position.lat());

    // Check to make sure the infoWindow is not already opened on this marker.
    if (infoWindow.marker != marker) {
        infoWindow.marker = marker;
        infoWindow.setContent('<div id="text">' + marker.title + '</div>' + '<div id="text">' + marker.address + '</div>');
        infoWindow.open(map, marker);

        // Make sure the marker property is cleared if the infoWindow is closed.
        infoWindow.addListener('closeclick',function(){
            infoWindow.setMarker = null;
        });

        // Get the street View for the place.
        var streetView = new google.maps.StreetViewService();
        var radius = 50;

        function getStreetView(data, status) {

            // Check if the status of the google service is OK.
            // In case it's ok, then proceed with the panorama view.
            if( status == google.maps.StreetViewStatus.OK ) {

                var nearStreetViewLocation = data.location.latLng;
                var heading = google.maps.geometry.spherical.computeHeading(
                    nearStreetViewLocation, marker.position);
                infoWindow.setContent('<div>' + marker.title + '</div><div id="pano"></div');
                var panoramaOptions = {
                    position: nearStreetViewLocation,
                    pov: {
                        heading: heading,
                        pitch: 30
                    }
                };

                var panorama = new google.maps.StreetViewPanorama(
                    document.getElementById('pano'), panoramaOptions);

            } else {
                infoWindow.setContent('<div>' + marker.title + '</div>' + '<div>No Street View Found</div>');
            }
        }

        // Calling the above function with the marker data.
        streetView.getPanoramaByLocation(marker.position, radius, getStreetView);
        infoWindow.open(map, marker);
    }
}

标记会相应更新。但是,绑定到self.allPlaces的元素下的列表不会更新。 self.allPlaces()在函数this.searchedPlace()中被清除,然后重新创建。但这些变化并没有反映在网页上。

1 个答案:

答案 0 :(得分:1)

self.allPlaces = ko.observableArray([]);

this.searchedPlace中的此调用会重新创建一个新的observableArray,因此旧的所有订阅者都被省略了。

您应该使用清除数组 self.allPlaces([])相反,它为它分配一个空数组,然后继续处理相同的obsevable