2017-01-05 8 views
1

私はJSON形式の配列(プロジェクト)を持っています。対象プロジェクトは、フィールドがあります。オブジェクトの角フィルタ複数の文字列

"name":"pname", 
"id":"1", 
"keywords":"aab bb cc" 

私は入力フォームng-model="searchText"にフィルタを接続して検索するために、複数の文字列を使用したい

<div ng-repeat="p in projects | filter : searchText"> 
    {{p.name}}, {{p.id}} etc. 
</div> 

を使用してdivタグでこれらのオブジェクトを表示します。たとえば、検索: "pname aa bb"とすると上記のプロジェクトが表示されます。

私はカスタムフィルタを使用してsearchTextを分割する必要があることを知っています。しかし、文字列配列をフィルタリングする方法は、JSONオブジェクトでは機能しないようです。違いはなんですか?

単純な文字列配列の試み。 ['aab', 'bb', 'cc']オブジェクト配列のために働かなかったこと:

.filter("myFilter", function(){ 
return function(input, searchText){ 
    var returnArray = []; 
    var searchTextSplit = searchText.toLowerCase().split(' '); 
    for(var x = 0; x < input.length; x++){ 
     var count = 0; 
     for(var y = 0; y < searchTextSplit.length; y++){ 
      if(input[x].toLowerCase().indexOf(searchTextSplit[y]) !== -1){ 
       count++; 
      } 
     } 
     if(count == searchTextSplit.length){ 
      returnArray.push(input[x]); 
     } 
    } 
    return returnArray; 
} 
}); 

は、どのように私はそれがオブジェクトに対して動作させるのですか?

答えて

1

しかし、文字列配列をフィルタリングするために働くのアプローチは、JSONオブジェクトで動作するようには思えません。違いはなんですか?

filterフィルタのexpression引数がstringであれば、角度は横切って一致される項目はobject型である場合つのみ特定のキーと値のペアで指定されたstringに一致するように試みます。角度ドキュメントから参照するため

は、:

ストリングは、アレイの内容との照合に使用されます。この文字列と一致する配列内の文字列プロパティを持つすべての文字列またはオブジェクトが返されます。これはネストされたオブジェクトのプロパティにも適用されます。

あなたが望むように見える行動は、複数キーと値のペア間の値でstringを一致させることです。

これは、expression引数に述語functionを渡すことができるという事実を利用して、スマートなマッチング動作を導入することができます。

以下を参照してください。Plunker作業用溶液です。より多くの場合、つまり配列値を扱うように、さらに最適化または調整することができます。

私の解説は、オブジェクトにネストされたプロパティがあっても一致する用語をサポートしていることに注意してください。

+0

プロパティキーを検索対象から除外する方法はありますか?オブジェクトは実際にはSQLクエリのJSON_encodeオブジェクトで、キーの1つはBLOBです。ブロブを含めると、フィルタが誤動作します。 (ng-repeat:dupes) – sandboxj

+1

もちろんです。オブジェクトをトラバースするために使用する関数を変更して、一連のプロパティキーを受け入れるように変更し、トラバース中にそれらを無視してスキップします(更新された['Plunker'](http://plnkr.co/edit/U1TOccm3pURetRTUul12?p=preview) )。しかし、 'ng-repeat'の重複エラーは、プロパティキーを除外することには関係していないと思われます。 Angularがあなたのオブジェクトをアイデンティティで区別できない場合、 'ng-repeat'に' track by $ index'を追加することができます(この[documentation](https://docs.angularjs.org/api/ng/)参照)。ディレクティブ/ ngRepeat#トラッキングと重複)を参照してください)。 – miqid

1

plunkerを参照してください。すべてのプロパティ値を結合し、正規表現を使用してすべての検索条件に一致させることができます。境界条件を追加しました。つまり、各キーワードの先頭に一致します。境界マッチングを行いたくない場合は、変更することができます。

pname aa bbと入力すると、searchTextがすべての条件に一致するため、オブジェクトが取得されます。しかし `pname aa zz 'はあなたのオブジェクトを返しません。

app.filter('myFilter', ['$filter', function($filter) { 
    var buildMatchingString = function(object) { 
     var matchingString = ''; 
     // Join all the property values into 1 string separated by a 'space' 
     // so that we can do boundary matching 
     angular.forEach(object, function(prop, key) { 
      matchingString += ((prop || '') + ' '); 
     }); 
     return matchingString; 
    }; 

    return function(list, searchText) { 
     if (!searchText) { 
      // Return everything if there is no user input 
      return list; 
     } 
     var result = []; 
     // Split all the search terms 
     var keywords = searchText.split(' '); 

     return $filter('filter')(list, function(elem) { 
      var matchingString = buildMatchingString(elem); 
      // Check that the properties of the object matches the 
      // beginning of ALL the search terms 
      for(var i = 0; i < keywords.length; i++) { 
       if (!matchingString.match(new RegExp('\\b' + keywords[i] + '.*', 'gi'))) { 
        return false; 
       }   
      } 
      return true; 
     }); 
    }; 
}]); 
0

あなたは、単にあなたのカスタムフィルタの角度内部の$フィルタ機能を使用することができます。

app.filter('myFilter', ['$filter', function($filter){ 
    return function(data, text){ 
     var textArr = text.split(' '); 
     angular.forEach(textArr, function(test){ 
      if(test){ 
       data = $filter('filter')(data, test); 
      } 
     }); 
     return data; 
    } 
}]); 

は、その後、例えば、カスタムフィルタにパラメータとして検索テキストを渡します

<li ng-repeat="obj in objects | myFilter:searchText">{{obj.name}}</li> 
関連する問題