2017-08-11 11 views
1

チェックボックスを使用して別の配列からリストをフィルタリングしようとしていますが、失敗しています。基本的に私は、各仕事の場所の配列をinlcudeジョブの配列を持っています。オプションのチェックボックスがあり、selectedLocationsの配列が作成されています。knockout.js内の別の配列から入れ子になったko.observableArrayをチェックボックスでフィルタリングする方法

上記のすべてが動作していますが、私が必要とするフィルタリングされたリストを達成できません。フィルタリングされたリストは表示されており、hiringManagerJobsとまったく同じですが、フィルタリングが機能していません。

以下に私のコードを掲載しました。問題は、viewModel.filteredJobs関数にあります。

KnockoutJsノックアウトビューモデルでJSON配列が

"chosenLocations": [ 
{ 
    "Type": 0, 
    "From": null, 
    "To": null, 
    "Value": "London", 
    "Count": 1 
}, 
{ 
    "Type": 0, 
    "From": null, 
    "To": null, 
    "Value": "Glasgow", 
    "Count": 1 
} 
], 


"hiringManagerJobs": [ 
    { 
    "Score": 1, 
    "Highlights": null, 
    "Document": { 
    "id": "1b41ce24-280d-4fe7-8488-d4babd522bc9", 
    "JobTitle": "Test HiringManagerFilterId", 
    "CompanyName": "Test Company", 
    "ExtUrl": "https://.....", 
    "Locations": [ 
     "London", 
     "Manchester", 
     "New York" 
     ], 
    "JobSummary": "blah blah blah", 
    "OgLogo": null, 
    "HiringManagerFilterId": "xjifu9fdasjkf985ed4" 
    } 
}, 
{ 
    "Score": 1, 
    "Highlights": null, 
    "Document": { 
    "id": "853880b3-fbae-4271-8034-7868c4de63a8", 
    "JobTitle": "Senior Manager - Software Development", 
    "CompanyName": "Test Company", 
    "ExtUrl": "https:......", 
    "Locations": [ 
     "London", 
     "Glasgow", 
     "Edinburgh" 
    ], 
    "JobSummary": "blah blah blah ", 
    "OgLogo": null, 
    "HiringManagerFilterId": "xjifu9fdasjkf985ed4" 
    } 
} 
], 

"LocationsFacets": [ 
{ 
    "Type": 0, 
    "From": null, 
    "To": null, 
    "Value": "Edinburgh", 
    "Count": 1 
}, 
{ 
    "Type": 0, 
    "From": null, 
    "To": null, 
    "Value": "Glasgow", 
    "Count": 1 
}, 
{ 
    "Type": 0, 
    "From": null, 
    "To": null, 
    "Value": "London", 
    "Count": 1 
} 

]の下のようなものです

var Search = function(){ 
var self = this; 

self.hiringManagerJobs = ko.observableArray(); 

self.hiringManagerFilterSearchTerm = ko.observable(); 
self.hiringManagerFilterId = document.getElementById('hiringManagerId').value 
self.LocationsFacets = ko.observableArray(); 
self.chosenLocations = ko.observableArray(); 
self.filteredJobs = ko.observableArray(); 


//self.filteredJobs = ko.observableArray(); 

searchByHiringManager = function() { 
    $.get('/... 
    }).done(function (data) { 
     self.hiringManagerJobs(data.Results); 
     self.LocationsFacets(data.Facets.Locations); 
    }) 
} 
searchByHiringManager(); 
} 

var viewModel = new Search(); 


viewModel.filteredJobs = ko.computed(function() { 
    var chosenLocations = ko.utils.arrayFilter(viewModel.LocationFacets, 
         function (p) { 
         return p.selected(); 
    }); 
    var jobs = viewModel.hiringManagerJobs(); 
    if (chosenLocations.length == 0) //if none selected return all 
     return jobs; 
    else { //other wise only return selected jobs 
     return ko.utils.arrayFilter(jobs, function(job){ 
     return ko.utils.arrayFilter(job.Locations, function(location){ 
     return ko.utils.arrayFilter(chosenLocations, 
            function(chosenLocation) { 
       return location == chosenLocation.Value; 

      }).length > 0; 
      }) 
     }) 

    } 
}) 

ko.applyBindings(viewModel); 

HTML

<!-- ko foreach: LocationsFacets --> 
    <input type="checkbox" data-bind="checkedValue: $data, checked: $root.chosenLocations" /> 
    <span data-bind="text: Value"></span> 
    <!-- /ko --> 

     <ul class="list-group" data-bind="foreach: filteredJobs"> 

      <li class="list-group-item" data-bind="with: Document"> 

       <p class="job-title media-heading" data-bind="text: JobTitle"></p> 

      </li> 

     </ul> 

+0

私はバイオリンで、あなたの問題を再現しようとしているが、一部のデータがdata.Facets.Locationsのために不足しているようです。たぶんあなたは一見して欠けているデータを埋めることができます。それがなければ、あなたを助けるのは難しいでしょう。 – Nisarg

+0

質問に位置ファセットを追加しました –

+0

投稿したコードに基づいて、filteredJobsが 'p.selected();'に基づいてフィルタリングしようとしていますが、 'p。これは常に空の配列を返し、すべてのジョブを返す関数が続きます。 "//選択されていない場合はすべて返されます" –

答えて

1

主な問題は、あなたが構造化されてきた方法であなたのデータを参照していないということですそれ。プログラムの以前の反復から残されていると思われるローカル定義chosenLocationsがあります。あなたはjob.Locationsを見ていますが、Locationsjob.Documentです。

私はArray.findのアナログとしてarrayFirstを使用しました。これは、追加のフィルタではなく、フィルタ内部のものに似ています。

var Search = function() { 
 
    var self = this; 
 

 
    self.hiringManagerJobs = ko.observableArray(); 
 
    self.hiringManagerFilterSearchTerm = ko.observable(); 
 
    self.hiringManagerFilterId = 'xjifu9fdasjkf985ed4'; 
 
    self.LocationsFacets = ko.observableArray(); 
 
    self.chosenLocations = ko.observableArray(); 
 
    self.filteredJobs = ko.observableArray(); 
 

 

 
    //self.filteredJobs = ko.observableArray(); 
 

 
    searchByHiringManager = function() { 
 
    self.hiringManagerJobs([{ 
 
     "Score": 1, 
 
     "Highlights": null, 
 
     "Document": { 
 
      "id": "1b41ce24-280d-4fe7-8488-d4babd522bc9", 
 
      "JobTitle": "Test HiringManagerFilterId", 
 
      "CompanyName": "Test Company", 
 
      "ExtUrl": "https://.....", 
 
      "Locations": [ 
 
      "London", 
 
      "Manchester", 
 
      "New York" 
 
      ], 
 
      "JobSummary": "blah blah blah", 
 
      "OgLogo": null, 
 
      "HiringManagerFilterId": "xjifu9fdasjkf985ed4" 
 
     } 
 
     }, 
 
     { 
 
     "Score": 1, 
 
     "Highlights": null, 
 
     "Document": { 
 
      "id": "853880b3-fbae-4271-8034-7868c4de63a8", 
 
      "JobTitle": "Senior Manager - Software Development", 
 
      "CompanyName": "Test Company", 
 
      "ExtUrl": "https:......", 
 
      "Locations": [ 
 
      "London", 
 
      "Glasgow", 
 
      "Edinburgh" 
 
      ], 
 
      "JobSummary": "blah blah blah ", 
 
      "OgLogo": null, 
 
      "HiringManagerFilterId": "xjifu9fdasjkf985ed4" 
 
     } 
 
     } 
 
    ]); 
 
    self.LocationsFacets([{ 
 
     "Type": 0, 
 
     "From": null, 
 
     "To": null, 
 
     "Value": "Edinburgh", 
 
     "Count": 1 
 
     }, 
 
     { 
 
     "Type": 0, 
 
     "From": null, 
 
     "To": null, 
 
     "Value": "Glasgow", 
 
     "Count": 1 
 
     }, 
 
     { 
 
     "Type": 0, 
 
     "From": null, 
 
     "To": null, 
 
     "Value": "London", 
 
     "Count": 1 
 
     } 
 
    ]); 
 
    } 
 
    searchByHiringManager(); 
 
} 
 

 
var viewModel = new Search(); 
 

 

 
viewModel.filteredJobs = ko.computed(function() { 
 
    const chosenLocations = viewModel.chosenLocations(); 
 
    const jobs = viewModel.hiringManagerJobs(); 
 

 
    if (chosenLocations.length == 0) //if none selected return all 
 
    return jobs; 
 
    else { //other wise only return selected jobs 
 
    const result = ko.utils.arrayFilter(jobs, function(job) { 
 
     return ko.utils.arrayFirst(job.Document.Locations, function (location) { 
 
     return ko.utils.arrayFirst(chosenLocations, function (cl) { 
 
      return cl.Value === location; 
 
     }); 
 
     }); 
 
    }); 
 
    return result; 
 
    } 
 
}) 
 

 
ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> 
 
<!-- ko foreach: LocationsFacets --> 
 
<input type="checkbox" data-bind="checkedValue: $data, checked: $root.chosenLocations" /> 
 
<span data-bind="text: Value"></span> 
 
<!-- /ko --> 
 

 
<ul class="list-group" data-bind="foreach: filteredJobs"> 
 
    <li class="list-group-item" data-bind="with: Document"> 
 
    <p class="job-title media-heading" data-bind="text: JobTitle"></p> 
 
    </li> 
 
</ul>

+0

ロイありがとうございます。とても有難い。 –

0

self.filteredJobs = ko.observableArray(); I冗長構成のため、viewModel.filteredJobsも使用しないでください。

のモデルでは、computedです。

注:self.LocationFacets()これは観測可能です。あなたはviewModel.LocationFacetsとしました。

self.filteredJobs = ko.computed(function() { 
    var chosenLocations = ko.utils.arrayFilter(self.LocationFacets(), function (p) { 
     return p.selected(); 
    }); 
    var jobs = self.hiringManagerJobs(); 
    if (chosenLocations.length == 0) { 
     // if none selected return all 
     return jobs; 
    } 
    else { 
     // other wise only return selected jobs 
     return ko.utils.arrayFilter(jobs, function(job) { 
      return ko.utils.arrayFilter(job.Locations, function(location){ 
       return ko.utils.arrayFilter(chosenLocations, function(chosenLocation) { 
        return location == chosenLocation.Value; 
       }).length > 0; 
      }) 
     }) 
    } 
}) 

あなたがfilteredJobsを述べる注意が働いている、それはあなたが場所ファセットを選択したとき、それはfilteredJobsをトリガしていないだけということです。 selectedが更新されていますが、が変更されることはありません。LocationFacetsまたはhiringManagerJobsに変更するとこれが更新されます。あなたは、ファセットの選択に変異させる配列を期待している場合は

、あなたはこれを必要になります

self.selected.subscribe(function (newValue) { 
    if (viewModel != null) 
      viewModel.LocationFacets.valueHasMutated(); 
}); 
+0

フィルタ処理されたジョブがその中で動作しています:filteredJobsはすべてのジョブを表示します。フィルタリングが機能していない、つまり問題です。選択した場所がビューモデルに読み込まれていますが、ジョブのリストはそれに応じてフィルタリングされません。私は問題がfilteredjobs関数内のelseステートメントのロジックにあると考えています。 –

関連する問題