2016-04-12 16 views
0

this postに基づいてフィルタを作成しました。 問題は、いくつかのオブジェクトでは、複数の値(値の配列)を同時に持つことができるプロパティを持っていることです(たとえば、ワインのタイプが同時にカテゴリ「ワイン」と「シャンパン」になる可能性があります) )。私は運がないとフィルターを変更しようとしています。角度 - 複数の値を持つプロパティを持つオブジェクトをフィルタリングする

<div ng-controller="myCtrl"> 
<div ng-repeat="(prop, ignoredValue) in wines[0]" ng-init="filter[prop]={}"> 
    <b>{{prop}}:</b><br /> 
    <span class="quarter" ng-repeat="opt in getOptionsFor(prop)"> 
     <b><input type="checkbox" ng-model="filter[prop][opt]" />&nbsp;{{opt}}</b> 
    </span> 
    <hr /> 
</div> 
<div ng-repeat="w in filtered=(wines | filter:filterByProperties)"> 
    {{w.name}} ({{w.category}}) 
</div> 

そして、私の角度ロジック:ここに私のhtmlです

var app = angular.module('myApp', []); 
app.controller('myCtrl', function ($scope) { 
$scope.wines = [ 
    { name: "Wine A", category: ["red"] }, 
    { name: "Wine B", category: ["red"] }, 
    { name: "wine C", category: ["white"] }, 
    { name: "Wine D", category: ["red"] }, 
    { name: "Wine E", category: ["red"] }, 
    { name: "wine F", category: ["champagne","white"] }, 
    { name: "wine G", category: ["champagne"]}, 
    { name: "wine H", category: ["champagne"] }  
]; 
$scope.filter = {}; 

$scope.getOptionsFor = function (propName) { 
    return ($scope.wines || []).map(function (w) { 
     return w[propName]; 
    }).filter(function (w, idx, arr) { 
     return arr.indexOf(w) === idx; 
    }); 
}; 

$scope.filterByProperties = function (wine) { 
    // Use this snippet for matching with AND 
    var matchesAND = true; 
    for (var prop in $scope.filter) { 
     if (noSubFilter($scope.filter[prop])) continue; 
     if (!$scope.filter[prop][wine[prop]]) { 
      matchesAND = false; 
      break; 
     } 
    } 
    return matchesAND; 
}; 

function noSubFilter(subFilterObj) { 
    for (var key in subFilterObj) { 
     if (subFilterObj[key]) return false; 
    } 
    return true; 
} 
}); 

私はオブジェクトが配列その複数の値を持つプロパティを持っているとき、それはとても仕事したいと思います(白とシャンパンの例のように)、オブジェクトはその1つ(またはその両方)を選択するだけで選択されます。前もって感謝します。

私は、私はこのような配列にすべてのカテゴリを変換推薦JsFiddle here

答えて

1

私はあなたが各プロパティのオブジェクトをフィルタリングしようとしていると思います。これが必要な場合は、すべてのプロパティと各プロパティのすべての値をチェックボックスとして一覧表示するコードを変更しました。

まず、各ワインを渡して使用可能なすべてのフィルタオプションを取得し、配列変数として設定します。重複も削除します。

各チェックボックスをオンにすると、filterByCurrentFilterメソッドは選択したすべてのフィルタを検索し、ワインがそれらの条件をすべてサポートしているかどうかをチェックします。

ここにはdemoがあります。

var app = angular.module('myApp', []); 
app.controller('myCtrl', function ($scope) { 
    $scope.wines = [ 
     { name: "Wine A", category: "red" }, 
     { name: "Wine B", category: "red" }, 
     { name: "wine C", category: "white" }, 
     { name: "Wine D", category: "red" }, 
     { name: "Wine E", category: "red" }, 
     { name: "wine F", category: ["champagne","white"] }, 
     { name: "wine G", category: "champagne"}, 
     { name: "wine H", category: "champagne" }  
    ]; 
    $scope.filter = {}; 

    $scope.getFilterOptions = function() { 
      var optsAsObj = $scope.wines.reduce(function(prev,current) { 
      for (field in current) { 
       prev[field] = prev[field] || []; 
       prev[field] = prev[field].concat(current[field]) 
       // remove duplicates 
       prev[field] = prev[field].filter(function(item, pos) { 
        return prev[field].indexOf(item) == pos; 
       }); 
      } 
      return prev; 
     }, {}); 

     var result = [] 
     for (key in optsAsObj) { 
      if (key == '$$hashKey') 
       continue; 
       result.push ({ name:key, values: optsAsObj[key] }) 
     } 

     return result; 

    }; 

    // for performance, calculate once and set it to a variable 
    $scope.filterOptions = $scope.getFilterOptions(); 

    $scope.filterByCurrentFilter = function (wine) { 
     var selectedFilters = {} 
     for (filterName in $scope.filter) { 

       // i.e filterName: name, category 
       var criteria = $scope.filter[filterName] 
      console.log('filterName:' + filterName) 
      // i.e criteria: { 'Wine A': true, 'Wine B': null, 'Wine C':false } 
      for (criteriaName in criteria) { 
        // i.e. criteriaName: 'Wine A' 
        if (criteria[criteriaName]) { 

         // a filter is true for criteriaName 
         var criteriaVals = selectedFilters[filterName] || [] 
        criteriaVals.push(criteriaName); 

        console.log('filterName:' + filterName + ' criteriaName:' + criteriaName + " criteriaVals:" + criteriaVals); 

        if (criteriaVals.length > 0) 
         selectedFilters[filterName] = criteriaVals 
       } 
      } 
     } 

     for (key in selectedFilters) { 
      console.log(key + ':' + selectedFilters[key]) 
       var filterVals = selectedFilters[key]; 
      if (!filterVals || filterVals.length == 0) 
        continue; 

      var wineVal = wine[key]; 
      wineVal = angular.isArray(wineVal) ? wineVal : [wineVal]; 

      var matches = wineVal.some (function(item) { 
        return filterVals.indexOf(item) != -1; 
      }); 

      if (!matches) 
       return false; 
     } 

     return true; 
    }; 

    function noFilter(filterObj) { 
     for (var key in filterObj) { 
      if (filterObj[key]) { 
       return false; 
      } 
     } 
     return true; 
    }    
}); 
+0

さて、私は論理を参照してください。もう1つのソリューションに加えて、すでに1つのプロパティ(f.ex名)でフィルタリングしていて、別のプロパティ(f.ex.カテゴリ)の値でフィルタすると、両方のセットが追加されず、それは交差点を作る。私はこれが問題をより良く解決すると思うので、これを有効に切り替えます。ありがとう! – Joe82

0

を更新しました:

$scope.wines = [ 
    { name: "Wine A", category: ["red"] }, 
    { name: "Wine B", category: ["red"] }, 
    { name: "wine C", category: ["white"] }, 
    { name: "Wine D", category: ["red"] }, 
    { name: "Wine E", category: ["red"] }, 
    { name: "wine F", category: ["champagne","white"] }, 
    { name: "wine G", category: ["champagne"]}, 
    { name: "wine H", category: ["champagne"] }  
]; 

その後、あなたはどこにでも配列のように、このプロパティを扱うことができます。より一貫して読みやすくなります。

+0

あなたは完全に正しいです。編集されました。 – Joe82

1

これは動作します:

var app = angular.module('myApp', []); 
app.controller('myCtrl', function ($scope) { 
    $scope.wines = [ 
     { name: "Wine A", category: "red" }, 
     { name: "Wine B", category: "red" }, 
     { name: "wine C", category: "white" }, 
     { name: "Wine D", category: "red" }, 
     { name: "Wine E", category: "red" }, 
     { name: "wine F", category: ["champagne","white"] }, 
     { name: "wine G", category: "champagne"}, 
     { name: "wine H", category: "champagne" }  
    ]; 
    $scope.filter = {}; 

    $scope.getOptionsFor = function (propName) { 
     return ($scope.wines || []).map(function (w) { 
     if(w[propName] instanceof Array) 
     { 
      for (var key in w[propName]) { 
      return w[propName][key]; 
      } 
     }else{ 
      return w[propName]; 
      } 
     }).filter(function (w, idx, arr) { 
      return arr.indexOf(w) === idx; 
     }); 
    }; 

    $scope.filterByProperties = function (wine) { 
     // Use this snippet for matching with AND 
     var matchesAND = true; 
     for (var prop in $scope.filter) { 
      if (noSubFilter($scope.filter[prop])) continue; 
      if(wine[prop] instanceof Array) 
      { 
       for (var key in wine[prop]) { 
         if (!$scope.filter[prop][wine[prop][key]]){ 
        matchesAND = false; 
        }else{ 
        matchesAND = true; 
        break; 
        } 
       } 
      } 
      else if (!$scope.filter[prop][wine[prop]]) { 
       matchesAND = false; 
       break; 
      } 
     } 
     return matchesAND; 
    }; 

    function noSubFilter(subFilterObj) { 
     for (var key in subFilterObj) { 
      if (subFilterObj[key]) return false; 
     } 
     return true; 
    } 
}); 

http://jsfiddle.net/8d6f5fdf/4/

+0

完璧に動作します。正しいとマークされています。ありがとう! – Joe82

+0

あなたは大歓迎です! – sreeramu

関連する問題