角度过滤器数组按特定属性值

时间:2015-07-27 10:16:28

标签: angularjs filter ng-repeat

我在这篇文章的接受答案中找到了我问题的一半答案。 How do I filter an array with AngularJS and use a property of the filtered object as the ng-model attribute?

我想知道是否可以通过另一个会创建这些对象数组的字段进行过滤,然后使用该数组中两个不同对象的值。

类似的东西......(带有ng-show =“data.Options.HasMap”的td)

<tbody>
            <tr ng-repeat="row in data.Rows">
                <td ng-repeat="col in row.Columns" ng-show="{{col.Visible}}">
                    {{ col.Value }}
                </td>
                <td ng-show="data.Options.HasMap" ng-repeat="hidden in row.Columns | filter:{Visible:false} track by $index">
                    {{hidden.Value | filter:{HeaderText:'Latitude'}}} , {{hidden.Value | filter:{HeaderText:'Longitude'}}}
                </td>
                <td ng-show="data.Options.HasSuppression">

                </td>
                <td ng-show="data.Options.HasAction">

                </td>
            </tr>
        </tbody>

我的Json文件有一系列列,如...

"Columns": [{
                 "HeaderText": "R1 - F1",
                 "Value": "data1",
                 "Visible": true
         },...

我希望将列拉出Visible:false,然后选择具有特定HeaderTexts的两个不同对象的值。

对不起,如果这听起来很混乱。任何帮助,将不胜感激。我对Angular很新,只是想弄清楚事情!

修改。 只是要指出我可以得到我需要的一个列对象。

            <td ng-show="data.Options.HasMap" ng-repeat="hidden in row.Columns | filter:{HeaderText:'Latitude'} track by $index">
                {{ hidden.Value }}
            </td>

但我真的需要Latitude和Longitude列对象来创建一个带有查询字符串变量的url。

我也试过......

<td ng-show="data.Options.HasMap">
                    {{ row.Columns.Value | filter:{HeaderText:'Latitude'} }} , {{ row.Columns.Value | filter:{HeaderText:'Longitude'} }}
                </td>

2 个答案:

答案 0 :(得分:0)

此行的值为hidden.Value(上例中为"R1 - F1"),并对其应用过滤器{ HeaderText: 'Latitude'}

{{hidden.Value | filter:{HeaderText:'Latitude'}}} , {{hidden.Value | filter:{HeaderText:'Longitude'}}}

您尝试使用针对对象数组的过滤器过滤字符串;这将只返回一个空数组,肯定不是你想要的。从你的例子中不清楚经度&#39;经度&#39;和纬度&#39;属性已定义。也许你想再次过滤列列表?就像是:

我不完全确定您要尝试做什么,请解释定义纬度/经度属性的位置。

另一件需要关注的是自定义过滤器,这些也可能有所帮助。看看Using filter to create array, then using that array to filter ng-options

修改

要使用HeaderText =&#34; Latitude&#34;和HeaderText =&#34;经度&#34;获取两列,您可以执行以下操作:

<span ng-repeat="col in row.Columns | filter:{HeaderText: "Latitude"}>

如果这不符合您的需求,请查看自定义过滤器。这是一个示例,可以根据您传入的任何值匹配标题文本进行过滤:

app.filter('filterByHeaderText', function() {
    return function(input, headerText) {
      // Input is the array to be filtered, 
      input = input || [];
      headerText = headerText || [];

      var output = [];
      for (var i = 0; i < input.length; i++) {
        for (var j = 0; j < headerText.length; j++) {
          // If input matches any of the headerText, then add it to the list
          if (input[i].headerText.indexOf(headerText[j].trim()) >= 0) {
            output.push(input[i]);
            break;
          }
        }
      }

      return output;
    };
  })

然后可以像这样使用此过滤器:

<span ng-repeat="item in row.Columns | filterByHeaderText: ['Latitude', 'Longitude']">

答案 1 :(得分:0)

对不起,这是我的第一个答案。我像这样过滤数组的自定义过滤器。 假设我们有这样的JSON对象数组:

var myArray=[{prop1:"val1", prop2:"val2", ...}, ...]

搜索参数在property name : property value对中定义,其结构应如下所示:

var examplePairs={
      prop1:"val1",
      prop2:["val2", "val3"],
      prop4:{eqStart:true, eqEnd:false, iStart:123, iEnd: 321}
      };

此示例在数组中搜索属性prop1的值为val1且属性prop2的值为val2val3且属性为prop3的所有匹配项来自区间[123,321>

注意:对于区间搜索,数组中对象内的数据必须是数字(不应该用引号定义)。

评论中有解释。 对于您的特定情况调用过滤器,如下所示:

 {{ pairs={HeaderText:['Latitude', 'Longitude'], Visible:true} }}
 <span ng-repeat="col in row.Columns | jsonArrayMultiFilter : pairs >

或者从控制器调用过滤器,如下所示:

var pairs={HeaderText:['Latitude', 'Longitude'], Visible:true}
 $scope.row.Columns=$filter('jsonArrayMultiFilter')($scope.row.Columns, pairs);

自定义过滤器代码:

.filter('jsonArrayMultiFilter',  function() {
return function(x, pairs) {
  //filters 
  //pairs = property:value pairs 
  //in case same properties can have multiple value pairs should be defined as followed
  // {property:[value1, value2]}
  //if value of property fits inside interval it should be defined as followed
  // {property:{eqStart:true, eqEnd:false, iStart:"start of interval", iEnd:"end of interval"}}
  //  if value in data is string it searches if string contains searched value 
  var keys=Object.keys(pairs);
  //console.log(keys);
  var newData=[];
  var counter, tempCount, expression;
  for (var i=0;i<x.length;i++){
    //iterate data then apply multiple filters
    //set counter value 0 for each itteration trough data
    //if all pairs satisfies conditions counter should equal (keys.length - 1)
    //for effitiency when condition is not satisfied loop should be broken on first fail
    counter=0;
    for (var j=0; j < keys.length; j++ ){
      //iterrate through pairs
      if (pairs[keys[j]].constructor === Array){
        //if property has multiple values itterate trough values
        tempCount=counter;
        for (var k=0; k < pairs[keys[j]].length; k++){
          //create regexp to perform case insensitive search
          var rExp = new RegExp(pairs[keys[j]][k], "i");
          //if value is a string expression searches the string if it is number finds exact match
          expression=(typeof x[i][keys[j]] == 'string' || x[i][keys[j]] instanceof String)?x[i][keys[j]].search(rExp)>-1:x[i][keys[j]]==pairs[keys[j]][k];
          if (expression){
            counter++;
          }
        }
        if (tempCount==counter){
          //break itteration because one condition isn't satisfied for data x[i]
          break;
        }
      }else{
        //if not array but is object and property['iStart'] is not null and not undefined check if value is from interval
        if( typeof pairs[keys[j]]['iStart'] !== 'undefined' && pairs[keys[j]]['iStart'] !== null ){
          // if value is from interval
          var leftLimit=pairs[keys[j]]['eqStart']?x[i][keys[j]] >= pairs[keys[j]]['iStart']:x[i][keys[j]] > pairs[keys[j]]['iStart'];
          var rightLimit=pairs[keys[j]]['eqEnd']?x[i][keys[j]] <= pairs[keys[j]]['iEnd']:x[i][keys[j]] < pairs[keys[j]]['iEnd'];
          if (leftLimit &&  rightLimit){
            counter++;
          }
          else{
            //break itteration because one condition isn't satisfied for data x[i]
            break;
          }
        }else{
          //create regexp to perform case insensitive search
          var rExp = new RegExp(pairs[keys[j]], "i");
          //if value is a string expression searches the string if it is number finds exact match
          expression=(typeof x[i][keys[j]] == 'string' || x[i][keys[j]] instanceof String)?x[i][keys[j]].search(rExp)>-1:x[i][keys[j]]==pairs[keys[j]];
          //if property has one value make comparsion
          if (x[i][keys[j]]==pairs[keys[j]]){
            counter++;
          }  
          else {
            //break itteration because condition isn't satisfied for data x[i]
            break;
          }
        }
      }
      //if all conditions are satisfied
      if (counter >= keys.length){
        newData.push(x[i]);
      }
    }
  }
  return newData;
};
})