【问题标题】:Angular filter array by specific property values按特定属性值的角度过滤器数组
【发布时间】:2015-07-27 10:16:27
【问题描述】:

我在这篇文章的已接受答案中找到了我的问题的一半答案。 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>

但我确实需要纬度和经度列对象来创建带有查询字符串变量的 url。

我也试过了……

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

【问题讨论】:

    标签: angularjs filter ng-repeat


    【解决方案1】:

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

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

    您正在尝试使用用于对象数组的过滤器来过滤字符串;这只会返回一个空数组,肯定不是你想要的。从您的示例中不清楚“经度”和“纬度”属性的定义位置。也许您想再次过滤列列表?就像是:

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

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

    编辑

    要获取 HeaderText = "Latitude" 和 HeaderText = "Longitude" 的两列,您可以这样做:

    <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']">
    

    【讨论】:

    • 对不起,我应该提到经度和纬度属性实际上是列中的对象。所以我想拉两个列对象,一个具有“纬度”的 HeaderText 属性,一个具有“经度”的 HeaderText 属性。 - 这可能吗?
    【解决方案2】:

    对不起,这是我在这里的第一个答案。我为这样的过滤数组制作了自定义过滤器。 假设我们有这样的 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&gt; 的所有匹配项

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

    cmets中有解释。 对于您的特定案例呼叫过滤器,如下所示:

     {{ 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;
    };
    })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-16
      • 2019-04-15
      • 1970-01-01
      • 1970-01-01
      • 2015-10-17
      • 2019-12-12
      • 2021-08-05
      • 1970-01-01
      相关资源
      最近更新 更多