简体   繁体   中英

knockoutjs Google Maps API show all markers

Building a Google map page with a hardcoded array of marker locations. There's a search box that filters the visible markers on the screen using knockout. The idea is that as you enter each letter into the search box, knockout filters the markers you see on screen. This all works fine, but if I enter a few letters into the search box and then clear it, all of the markers don't re-appear on the screen. I know it should be a simple conditional, but for the life of me I can't get it working. Here's the pertinent code:

var locations = [
    {
        title: "Location 1",
        latlong: { lat: 25.55555, lng: -80.55555 },
        street: "123 Main St",
        city: "Anytown, USA 12345",
        id: 0,
        showLoc: ko.observable(true),
        visible: ko.observable(true),
    },
    {
        title: "Location 2",
        latlong: { lat: 27.77777, lng: -81.11111 },
        street: "456 Main St",
        city: "Anytown, USA 12345",        
        id: 1,
        showLoc: ko.observable(true),
        visible: ko.observable(true),
    }]

//loop to drop markers on map and add marker properties
function createMarkers() {
    for (i = 0; i < locations.length; i++) {
        locations[i].marker = new google.maps.Marker({
            position: locations[i].latlong,
            map: map,
            title: locations[i].title,
            animation: google.maps.Animation.DROP,
            id: i
        });
    }
}

//sets marker visibility
function setMarkerVisibility() {
    for (i = 0; i < locations.length; i++) {
        locations[i].marker.setVisible(locations[i].visible);
    }
}


//knockout viewmodel - handles search locations array and filtering
function AppViewModel() {
    query = ko.observable('');
    this.locations = ko.computed(function () {
        var self = this;
        var search = self.query().toLowerCase();
        return ko.utils.arrayFilter(locations, function (loc) {
            //I've tried adding an || query('') here, or an else if, but no luck
            if (loc.title.toLowerCase().indexOf(search) >= 0 || (query(''))) {
                loc.showLoc(true);
                loc.visible = true;
            } else {
                loc.showLoc(false);
                loc.visible = false;
                setMarkerVisibility();
            }
        });
    });
}

I am not sure but it looks like there may be an issue with your if statement in that the (query('')) statement will always be false. You are setting the variable "query" as an empty observable, then using the syntax for placing a value into an observable as far as I can tell. I am guessing that you want to show all markers if your search input is empty. I think that you would want to use your current variable for measuring if the input is empty in order to show all. The first part of the if statement also is missing the setMarkerVisibility() call.

//knockout viewmodel - handles search locations array and filtering
function AppViewModel() {
    query = ko.observable('');
    this.locations = ko.computed(function () {
        var self = this;
        var search = self.query().toLowerCase();
        return ko.utils.arrayFilter(locations, function (loc) {
            //Show all location markers if they contain the search text or if the search text is empty
            if (loc.title.toLowerCase().indexOf(search) >= 0 || search == '') {
                loc.showLoc(true);
                loc.visible = true;
            } else {
                loc.showLoc(false);
                loc.visible = false;
            }
            setMarkerVisibility();
        });
    });
}

So here's the answer: The ko.computed function executes in the script before createMarkers(), so I needed to add an IF that loops through the array and verifys that the markers have already been created

function AppViewModel() {
    query = ko.observable('');
    this.locations = ko.computed(function () {
        var self = this;
        var search = self.query().toLowerCase();

        if (!search) {
            for (i = 0; i < locations.length; i++) {
                if (locations[i].marker) //checks to see that markers exist
        locations[i].marker.setVisible(true);
            }
        }

        return ko.utils.arrayFilter(locations, function (loc) {               
            if (loc.title.toLowerCase().indexOf(search) >= 0 || search == '') {
                loc.showLoc(true);
                loc.visible = true;
            } else {
                loc.showLoc(false);
                loc.visible = false;
            }
            setMarkerVisibility();
        });
    });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM