2017-08-23 2 views
1

レストランのリストを取得してGoogleマップに表示するアプリを開発しています。このリストも表示されるので、ユーザーはレストランの名前を見ることができます。Knockout.Jsを使用してフィルタリングされたリストの結果を表示するにはどうすればよいですか?

Knockout.jsを使用してリストをフィルタリングして、誰かがレストランの名前を入力し始めたときに、そのクエリに一致するものだけが表示されるようにします。

HTML +ノックアウトバインディング

<div> 
    <div id="search"> 
    <input type="text" placeholder="Filter" data-bind="textInput:query"> 
    </div> 
    <ul data-bind="foreach: restaurants"> 
    <li data-bind="text: name"></li> 
    </ul> 
</div> 
<div id="map"></div> 

はJavaScript

var restaurants = [ 
    {name: 'Chez Simone', location: {lat:48.8603937, lng: 2.3430545}}, 
    {name: 'Cafe Coutume', location: {lat:48.851599, lng: 2.3162123}}, 
    {name: 'Café Pinson', location: {lat:48.863732, lng: 2.3631037}}, 
    {name: 'Sol Semilla', location: {lat:48.8730959, lng: 2.363135900000001}}, 
    {name: 'Juice Lab Marais', location: {lat:48.8563595, lng: 2.3637123}} 
]; 

//viewModel 
var viewModel = function(){ 
    var self = this; 
    self.restaurantList = ko.observableArray(restaurants); 

    //Stores user input 
    self.query = ko.observable(''); 

    // Filters through observableArray and filters results using util.arrayFilter(); 
    self.search = ko.computed(function(){ 
    var query = this.query().toLowerCase(); 
    if(!query) { 
     return self.restaurantList(); 
    } else { 
     //go through restaurant list and for each restaurant, check if the letters in query 
     // appear in restaurant name. If so, display name. else don't. 
     var restaurantList = self.restaurantList(); 
     for(i = 0; i < restaurantList.length; i++){ 
     var restaurant = restaurantList[i]; 
     var restaurantName = restaurant.name; 
     // check if query letter/s appears in restaurant name 
     if(restaurantName.toLowerCase().indexOf(query) > -1){ 
     // Help! This is where I'm stuck. 
     return restaurantName; 
     } 
     } 
    } 
    }, self); 
}; // viewModel ends ` 

私がこれまで持っている論理が働く - 私はconsole.log(restaurantName)を使用する場合、それが唯一の正しい出力しますレストラン。私はそれをビューに表示することはできません。

リストビューに表示するにはどうすればよいですか?

+0

これはhttps://stackoverflow.com/questions/45422066/set-marker-visible-with-knockout-js-ko-utils-arrayfilterと非常によく似ています。あなたの場所を使用するようにフィドルを更新しました。 https://jsfiddle.net/dy70fe16/3/ –

+0

[マーカーをノックアウトJS ko.utils.arrayFilterで表示する設定]の可能な複製(https://stackoverflow.com/questions/45422066/set-marker-visible-with- knockout-js-ko-utils-arrayfilter) –

答えて

2

あなたcomputedプロパティsearchは常にarrayので、あなたがフィルターコレクションにforeachをバインドすることができますを返す必要があります。あなたが探していない場合は、すべてのレストランを示し、言い換えれば

if (!query) return self.restaurantList(); 

はすでに最初の部分を得ました。

また、ループして戻った部分を除いて、最後の部分のほとんどを機能させることに成功しました。

クエリに一致する項目の配列を作成するには、restaurantList.filter(または、あなたのコメントに記載されているように、util.arrayFilter)を使用する必要があります。

return self.restaurantList().filter(function(restaurant) { 
    return (restaurant.name.toLowerCase().indexOf(query) > -1) 
}); 

その後、foreach: searchで、あなたは以下のスニペット取得します:GoogleマップのUIで任意のマーカーを更新する

var restaurants = [ 
 
    {name: 'Chez Simone', location: {lat:48.8603937, lng: 2.3430545}}, 
 
    {name: 'Cafe Coutume', location: {lat:48.851599, lng: 2.3162123}}, 
 
    {name: 'Café Pinson', location: {lat:48.863732, lng: 2.3631037}}, 
 
    {name: 'Sol Semilla', location: {lat:48.8730959, lng: 2.363135900000001}}, 
 
    {name: 'Juice Lab Marais', location: {lat:48.8563595, lng: 2.3637123}} 
 
]; 
 

 
//viewModel 
 
var viewModel = function(){ 
 
    var self = this; 
 
    self.restaurantList = ko.observableArray(restaurants); 
 

 
    //Stores user input 
 
    self.query = ko.observable(''); 
 

 
    self.search = ko.computed(function(){ 
 
    var query = this.query().toLowerCase(); 
 
    if(!query) { 
 
     return self.restaurantList(); 
 
    } else { 
 
     var restaurantList = self.restaurantList(); 
 
     return restaurantList.filter(function(restaurant) { 
 
     var restaurantName = restaurant.name; 
 
     return (restaurantName.toLowerCase().indexOf(query) > -1) 
 
     }); 
 
    } 
 
    }, self); 
 
}; 
 

 
ko.applyBindings(new viewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> 
 

 
<div> 
 
    <div id="search"> 
 
    <input type="text" placeholder="Filter" data-bind="textInput:query"> 
 
    </div> 
 
    <ul data-bind="foreach: search"> 
 
    <li data-bind="text: name"></li> 
 
    </ul> 
 
</div> 
 
<div id="map"></div>

注意を、あなたがする必要がありますsearchに登録し、それに従って地図を更新してください。

+0

助けてくれてありがとう。私はそれを試しましたが、入力に何かを入力すると何も変わりません。言い換えれば、リストはフィルタリングされず、同じままです。なぜそれが可能なのか? –

+0

元のソースではなく、計算されたリストを参照するようバインディングを変更しますか? – user3297291

+0

それはそれでした。私はforeachを検索するように変更することを忘れていました。 –

関連する問題