Angular.js自定义过滤器(过滤对象数组)

时间:2018-12-27 01:17:21

标签: javascript angularjs

我正在使用angularjs制作Web应用程序。我有一个从后端以以下结构获取的帖子列表:

[
  {
    post: {
      postID: 1,
      title: "sample title", 
      body: "so many paragraphs here", 
      post_date: "2018-12-26 02:21:35"
    } 
    tags: [
      {
        tagTitle: "training"
      }, 
      {
        tagTitle: "another tag" 
      } 
    ] 
  } 
]

我想根据我单击的标签过滤这些帖子。假设我点击了培训,我想显示在其标签的数组中具有 training 条目的帖子。

由于它是一个angularjs Web应用程序,因此ui-sref是posts(filter:'training'),而路径(url)将是posts?filter = training。

我用以下代码创建了一个过滤器:

function postsFilter() {
  return function (collection, params) {
    return collection.filter(function (item) {
      var i, tagsArray = item.tags, len = tagsArray.length;
      for (i = 0; i < len; ++i) {
        return tagsArray[i].tagTitle === (
          params.filter === "none" ? tagsArray[i].tagTitle : 
            params.filter;) 
        } 
    });
  };
}

angular.module('app').filter('postsFilter', postsFilter);

在控制器中,我有以下代码;

function PostsController($filter) {
  angular.extend(this, {
    $onInit: () => {
      this.filteredPosts = $filter('postsFilter')(this.posts, this.filter);
    } 
  } 
}

在组件中,我有以下代码:

const posts = {
  bindings: {
    posts: '<', 
    filter: '<' 
  }, 
  templateUrl: 'path/to/my/posts.html',
  controller: 'postsController'
};

angular.module('app').component('posts', posts).config(
[
  '$stateProvider', function ($stateProvider) {
    $stateProvider.state (
      'posts', {
        url: '/posts?filter',
        component: 'posts', 
        params: {
          filter: {
            value: 'none'
          }
        }, 
        resolve: {
          posts: ['PostsService', function (PostsService) {
            return PostsService.getPostList();
        }],
        filter: ['$transition$', function ($transition$) {
          return $transition$.params();
        }]
      } 
    }
  );
  } 
]);

然后在posts.html中,要显示过滤后的帖子,例如:

<div ng-repeat='post in $ctrl.filteredPosts'>
  {{post.post.title}}
</div>

使用我当前的代码,当我单击链接以过滤帖子时(例如ui-sref ='posts({filter:'angularjs'})),帖子不会被过滤。网址更改,但帖子仍显示所有内容。默认情况下,帖子的网址显示 / posts?filter = none 。当我单击链接以过滤帖子时(假设标签为angularjs),URL更改为 / posts?filter = angularjs

我该如何纠正?

好的,现在将丢失的花括号放好后,它就可以工作了。我现在遇到的问题是,如果一个帖子有两个或多个标签,我将无法与其他标签一起过滤,而只能与第一个标签一起使用。

在此示例中,将仅使用 training 对其进行过滤,而不会使用另一个标签对其进行过滤。

2 个答案:

答案 0 :(得分:1)

如果某个帖子包含两个或多个标签,则无法与其他标签一起过滤,它只能与第一个标签一起使用

您可以尝试像这样形成URl

  

posts?filter = angularjs&training

然后在过滤器功能中,形成一个过滤器标签数组。因此,您将有两个数组-集合和过滤器。现在,对Filters Array中的每个过滤器使用javascript Array Includes函数。如下所示(您需要根据模型结构进行调整):

let filteredCollection = new Array();
filters.foreach((filter) => {
  if(collection.includes(filter)) {filteredCollection.push(collection)}
})

尽管这包括每次都解析两个数组,但这是目前最快的解决方案。

答案 1 :(得分:0)

我自己解决了这个问题。我将过滤器代码更改为以下代码(现在可以正常使用)。

function postsFilter () {
return function (collection, params) {
return collection.filter(function (item) {
var i, tagArray = item.tags, len = tagArray.length;
for (i = 0; i < len; ++i) {
if (params.filter === tagArray[i].tagTitle) {
return tagArray[i].tagTitle === (
params.filter === 'none' ? tagArray[i].tagTitle : params.filter
);
} else if (params.filter === 'none') {
return tagArray[i].tagTitle === (
params.filter === 'none' ? tagArray[i].tagTitle : params.filter
);
} 
} 
}
} 
}

这使我想发生的事情成为现实,但我不喜欢自己做的那种骇客。我重复了代码。如果有人可以帮助使其变得 DRY ,那就太好了。