Установка значения Observable not updating in view

У меня есть куча точечных объектов(маркеры на Google maps), я настраиваю прослушиватель событий click, который установит глобальную переменную «currentPlace», равную объекту Point, который нажимается, затем я обертываю currentPlace в наблюдаемой надежде, что представление изменится, например, боковое меню, которое будет отображать информацию об этом объекте Point.

"use strict";
var currentPlace;
...

function initMap() {
map = new google.maps.Map(mapDiv, {
    zoom: 12,
    center: center,
    disableDefaultUI: true,
    draggable: true,
    google.maps.event.addListenerOnce(map, "idle", function() {
      var viewModel = new ViewModel(collection);
        ko.applyBindings(viewModel);
    });
}

var Point = function(place) {
    var self = this;
    self.name = place.name;
    self.pos = place.pos;
    self.type = place.type;
    self.description = place.description;
    self.clicked = map.getZoom();
    /**
        Create a marker for this destination.
  */
    self.marker = new google.maps.Marker({
        map: map,
        position: place.pos,
        title: place.name,
        icon: image,
        optimized: false,
        animation: google.maps.Animation.DROP
    });

    self.isVisible = ko.observable(false);
    /**
        Toggle for the visibility of each marker on map.
  */
  self.isVisible.subscribe(function(currentState) {
    if (currentState) {
      self.marker.setMap(map);
    } else {
      self.marker.setMap(null);
    }
  });

  self.isVisible(true);

  /**
        To re position the target marker and the map view to compensate for the shifted map view panel when the search menu pushes in from the left when the location is being clicked on the menu.
  */
    self.focusSearch = function() {
        map.setZoom(16);
        map.setCenter(self.marker.position);
        map.panBy(200,0);
        self.open();
    }
    /**
        To re position the target marker and the map view to compensate for the shifted map view panel when the menu slides in from the left when the location is being clicked on the menu.
  */
    self.focus = function() {
        map.setZoom(16);
        map.setCenter(self.marker.position);
        map.panBy(-200, 0);
        self.open();
    }
    /**
        Display the name and a brief description of the location in a infowindow for the corresponding marker. Also checks if the map view, in this case the zoom level has changed, if so then change the map view and re center it to the marker of the loaction that is selected. Applies to only when the regular menu is active.
    */
    self.open = function() {
        var contentString = "<h2>" + place.name + "</h2><br>";
        infowindow.setContent(contentString + place.description);
        infowindow.open(map, self.marker);
    }
    /**
        Dismiss the infowindow.
    */
    self.close = function() {
        infowindow.close();
        self.marker.setAnimation(null);
    }
    /**
        Additional event listeners for the marker.
    */
    self.marker.addListener("mouseover", function() {
        self.open();
        self.marker.setAnimation(google.maps.Animation.BOUNCE);
    });

    self.marker.addListener("mouseout", function() {
        self.marker.setAnimation(null);
    });

    self.marker.addListener("click", function() {
        currentPlace = self;
        map.setZoom(16);
        map.setCenter(self.marker.position);
        pushLeft.close();
        slideLeft.close();
        slideBottom.open();
        self.open();
    });
}
/**
        This is our ViewModel that handles displaying a menu of destinations, filter/search through the menu and finally displaying markers of these destinations on the map.
*/
var ViewModel = function(list) {
    var self = this;
    /**
     * Create a Place object for each object in the initial array and
     * place them in a new observable array.
    */
    self.allPlaces = ko.observableArray(list.map(function(place) {
        return new Point(place);
    }));

    self.search = ko.observable("");
    currentPlace = self.allPlaces()[0];
    self.selected = ko.observable();


    /**
     * Filter locations out of the menu view for any unmatched results.
     * Filter by name, description and type.
    */
    self.searchResult = ko.pureComputed(function() {
        var q = self.search().toLowerCase();
        return self.allPlaces().filter(function(place) {
            return ((place.name.toLowerCase().indexOf(q) >= 0) || (place.description.toLowerCase().indexOf(q) >= 0) || (place.type.toLowerCase().indexOf(q) >= 0));
        });
    });
    /**
     * Filter markers out of the map view for any unmatched results.
     * Filter by name, description and type.
    */
    self.filterMarkers = ko.computed(function () {
    var q  = self.search().toLowerCase();
    return ko.utils.arrayFilter(self.allPlaces(), function (place) {
        var doesMatch = ((place.name.toLowerCase().indexOf(q) >= 0) || (place.description.toLowerCase().indexOf(q) >= 0) || (place.type.toLowerCase().indexOf(q) >= 0));
        place.isVisible(doesMatch);
        return doesMatch;
    });
  });
}

1 ответ

  1. Нокаут так не работает. Единственный способ привязать графический интерфейс к модели представления — использовать объект наблюдения напрямую.

    В вашем случае лучше всего было бы переместить глобальную переменную currentPlace в модель представления как наблюдаемую. Чтобы получить к нему доступ позже, создайте глобальный экземпляр модели представления.

    var vm = new ViewModel();
    
    // Later on, access currentPlace this way:
    vm.currentPlace();