AngularJS 嵌套过滤器隐藏元素无缘属性

AngularJS nested filter hiding elements without destined property

我在一个项目中使用 AngularJS,我需要实现一个 select 框,其中包含一个过滤器到嵌套 属性。我的对象(我有一个数组,我正在通过 ng-repeat 遍历它们)的结构类似于:

{
  id: 1,
  name: 'Example',
  groups: [
    { id: 1, name: 'Group 1' },
    { id: 2, name: 'Group 2' }
  ]
}

我需要过滤元素的组ID,经过搜索我想出了两种方法:

1.

| filter: { $: { id: search.item_id } }

哪个有这些问题:

显然它会搜索任何名为 ID 的嵌套属性,因此如果我的主对象中有多个对象,并且还有一个名为 ID 的 属性,它会将其添加到过滤器中。示例:

{
  id: 2,
  name: 'Example 2',
  groups: [
    { id: 1, name: 'Group 1' },
    { id: 2, name: 'Group 2' }
  ],
  categories: [
    { id: 1, name: 'Cat 1' },
    { id: 2, name: 'Cat 2' }
  ]
}

过滤 ID 1 select 不仅会使用 ID 1 进行分组,还会对 ID 1 进行分类。

此外,使用此方法,即使在设置过滤器之前(search.item_id 模型为空),没有组的对象也会被过滤并且不会出现在列表中。这些对象是这样的:

{
  id: 3,
  name: 'Example 3',
  groups: []
}

另一种方式是:

2.

| filter: { groups: [{ id: search.item_id }] }

在这种情况下,问题是它根本不起作用,它会过滤所有内容,将列表留空,无论是否已设置或哪个选项已 selected。

我怎样才能让它发挥作用?我一直在搜索,找不到任何关于此的信息。过滤嵌套属性是(或应该是)非常基本的事情。


更新:

所以,xtx 第一个解决方案有点成功,但前提是我使用输入文本或数字,但我需要使用 select 框(更具体地说是 uib -dropdown,但在常规 select 中工作是下一步)。我的 select 框看起来像这样:

<select name="filter_classes_groups_test" ng-model="search.group_id">
  <option val="group.id" ng-repeat="group in classesGroups">{{ group.name }}</option>
</select>

当我与它交互时,没有任何反应。

如果创建自定义过滤器适合您,请按以下步骤操作:

app.filter('groupsFilter', function() {
  return function(input, groupId) {
    var out = [];

    if (!groupId || isNaN(parseInt(groupId))) {
      return input;
    }
    angular.forEach(input, function(item) {
      if (item.groups && angular.isArray(item.groups)) {
        angular.forEach(item.groups, function (group) {
          if (group.id === parseInt(groupId)) {
            out.push(item);
          }
        });
      }
    });
    return out;
  }
});

如您所见,自定义过滤器的名称为groupsFilter,并以group id作为参数进行搜索。可以像这样应用过滤器:

<div ng-repeat="item in data | groupsFilter:search.item_id">
  ...
</div>

更新:

无需创建自定义过滤器,您只需创建一个实现过滤逻辑的函数,范围如下:

$scope.groupsFilterLocal = function(value) {
  if (!$scope.search.item_id || isNaN(parseInt($scope.search.item_id))) {
    return true;
  }
  if (!value || !value.groups || !angular.isArray(value.groups)) {
    return false;
  }
  for (var i = 0; i < value.groups.length; i++) {
    if (value.groups[i].id === parseInt($scope.search.item_id)) {
      return true;
    }
  }
  return false;
};

然后像这样使用内置过滤器应用它:

<div ng-repeat="item in data | filter:groupsFilterLocal ">
  ...
</div>

请注意,在这种情况下,您不能将要搜索的值 (search.item_id) 传递到您的函数 groupsFilterLocal 中,就像上面的自定义过滤器 groupsFilter 所做的那样。所以 groupsFilterLocal 必须直接访问 search.item_id


更新 2:如何正确创建 select

当您在下拉列表中选择一个组时,过滤器未应用的原因在于您定义 select 的方式。而不是 selected 组的 id,search.group_id 获得分配的组名。 尝试定义 select 如下所示:

<select name="filter_classes_groups_test" ng-model="search.item_id" ng-options="group.id as group.name for group in classesGroups">
    <option value="">-- Choose Group --</option>
</select>

为确保 search.item_id 获得 selected 组的 ID(而不是其名称),请尝试在模板中的某处临时添加 {{ search.item_id }}