如何按角度表达式中的值过滤嵌套对象数组?

时间:2017-10-23 20:49:52

标签: angularjs angularjs-filter

我正在使用ng-repeat,其中每个对象(项目)如下所示:

{
    "properties":
                [
                {"value":"started","key":"status"},
                {"value":"somename","key":"name"},
                {"value":"10","key":"age"},
                ]
}

如何获取与'status'关键字对应的值

我试过了:

<span class="badge">{{item.properties['value'] | filter:{item:{properties:{key:'status'}}}}}</span>

但没有运气。

谢谢, 罗希斯

1 个答案:

答案 0 :(得分:1)

您想要过滤的内容是item.properties,而不是item.properties['value']。这将检查每个属性并返回符合您条件的数组项。由于只有一个匹配(我假设),您希望获取结果array[0]然后查看.value。这样做是通过将过滤器包装在括号中,然后像正常的对象数组一样访问它。

var app = angular.module("myApp", [])
.controller("myCtrl", function () {
  this.items =[{
    "properties":
    [
      {"value":"started","key":"status"},
      {"value":"somename","key":"name"},
      {"value":"10","key":"age"},
    ]
  },{
    "properties":
    [
      {"value":"finished","key":"status"},
      {"value":"somename","key":"name"},
      {"value":"15","key":"age"},
    ]
  },{
    "properties":
    [
      {"value":"error","key":"status"},
      {"value":"somename","key":"name"},
      {"value":"12","key":"age"},
    ]
  }];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp" ng-controller="myCtrl as Main">
  <div ng-repeat="item in Main.items">
    <div>{{ (item.properties | filter:{'key': 'status'})[0].value }}</div>
  </div>
</body>

修改

要使用嵌套属性搜索实现自己的自定义过滤器,您可以执行以下操作:

并非所有部分匹配的条件都在那里,但它应该足以让它很好地了解它是如何工作的。

var app = angular.module("myApp", [])
.filter("propertyFilter", function () {
  return function (items, property, value, strict) {
    return items.filter(function (item) {
      var propertyChain = property.split(".");
      var _propToCheck = item;
      // step through nested properties
      for(var prop of propertyChain) {
        if (_propToCheck.hasOwnProperty(prop)) {
          _propToCheck = _propToCheck[prop];
        }
        else {
          // return false if property does not exist
          return false;
        }
      }
      if (strict) {
        // exact matches only
        return _propToCheck === value;
      }
      else {
        // partial matching -- incomplete, but enough to show an example
        if (typeof _propToCheck === "string"){
          return _propToCheck.toLowerCase().indexOf(value.toLowerCase()) > -1;
        }
        else if (_propToCheck instanceof Array) {
          return _propTocheck.some(function (elem) {
            return _propToCheck.toLowerCase().indexOf(value.toLowerCase()) > -1;
          })
        }
        else {
          return _propToCheck == value;
        }
      }
    });
  }
})
.controller("myCtrl", function () {
  this.items =[{
    "properties":
    [
      {"value":"started","key":{"internalKey": {"_internalInternalKey": 'status'}}},
      {"value":"somename","key":"name"},
      {"value":"10","key":"age"},
    ]
  },{
    "properties":
    [
      {"value":"finished","key":{"internalKey": "status"}},
      {"value":"somename","key":"name"},
      {"value":"15","key":"age"},
    ]
  },{
    "properties":
    [
      {"value":"error","key":"status"},
      {"value":"somename","key":"name"},
      {"value":"12","key":"age"},
    ]
  }];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp" ng-controller="myCtrl as Main">
  <div ng-repeat="item in Main.items" style="margin: 10px;">
    <div>key: {{ (item.properties | propertyFilter:'key':'status')[0].value }}</div>
    <div>key.internalKey: {{ (item.properties | propertyFilter:'key.internalKey':'status')[0].value }}</div>
    <div>key.internalKey._internalInternalKey: {{ (item.properties | propertyFilter:'key.internalKey._internalInternalKey':'status')[0].value }}</div>
  </div>
</body>