2016-10-02 15 views
0

私はポイントオブジェクト(Googleマップ上のマーカー)の束を持っています。クリックしたポイントオブジェクトに等しいグローバル変数 "currentPlace"を設定するクリックイベントリスナーを設定しました。そのPointオブジェクトの情報を表示するサイドメニューなど、ビューが変更されることを望むオブザーバブルにcurrentPlaceをラップします。Observableの設定値が表示で更新されない

"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; 
    }); 
    }); 
} 
+0

なぜcurrentplaceがグローバルで、なぜそれが観測可能でないのですか? –

答えて

0

ノックアウトはそのようには機能しません。 GUIをビューモデルに結び付ける唯一の方法は、オブザーバブルを直接使用することです。

あなたのケースでは、グローバルなcurrentPlace変数をオブザーバブルとしてビューモデルに移動することをお勧めします。後でそれにアクセスするには、ビューモデルのグローバルインスタンスを作成します。

var vm = new ViewModel(); 

// Later on, access currentPlace this way: 
vm.currentPlace(); 
+0

あなたは正しいです!私はそれを動作させるためにコードを3行追加するだけで済みました。最も外側のスコープにvar viewModelを宣言して、Pointオブジェクトがそのスコープにアクセスできるようにします。次にviewModel内部で行う。self.selected = ko.observable(self.allPlaces()[0]);もし私がobservableを空白のままにしておくと、ビューモデルはhtmlに選択されたバインディングとしてエラーを投げるので、必須の最初の選択されたオブジェクトを設定します。最後に、マーカで偶数リスナをクリックし、viewModel.selected = selfを追加して、マーカがクリックされるたびに選択されたオブザーバブルが更新されるようにします。ありがとう! –

関連する問題