简体   繁体   English

Angular.js中的过滤指令

[英]Filtering directive in Angular.js

I'm trying to develop a single web application which is a blog, displaying posts. 我正在尝试开发一个单独的Web应用程序,即博客,显示帖子。 They are included in a template by the ng-repeat directive: ng-repeat指令将它们包含在模板中:

   <div class="post" data-ng-repeat="post in postList ">
        <div class="date">published: {{post.published_at | date:'dd-MM-yyyy, HH:mm'}}</div>
            <a class="btn btn-default" data-ng-click="editPost(post)"><span class="glyphicon glyphicon-pencil"></span></a>
            <a class="btn btn-default" data-ng-click="deletePost(post)"><span class="glyphicon glyphicon-remove"></span></a>
            <h1><a href="">{{post.title}}</a></h1>
            <p>{{post.text}}</p>
        </div>
   </div>      

They have fields, such as title, text and publishing date, defined in the controller. 它们具有在控制器中定义的字段,例如标题,文本和发布日期。 I'd like to filter them by various criteria. 我想按各种标准过滤它们。 For this purpose, I tried to implement my own custom filter (so that I can filter by more than 1 field): 为此,我尝试实现自己的自定义过滤器(以便可以按多个字段进行过滤):

angular.module("blog").
filter('bytitle', function() {
return function(posts, title) {
  var out = [];
  // Filter logic here, adding matches to the out var.
  var i;
  for(i = 0; i < posts.length; i++){
     if(posts[i].title.indexOf(title) >=0){
        out.push(posts[i]);
     }
  }
  return out;
}
});

however, if I run the javascript console, I get the following error, caused only by the presence of the code above: 但是,如果我运行javascript控制台,则会出现以下错误,该错误仅由上述代码的存在引起:

Argument 'postController' is not a function, got undefined

I'm new to angular , and I'm not really sure what this means. 我是angular新手,我不确定这意味着什么。 Any ideas? 有任何想法吗?

The entire source code: http://plnkr.co/edit/suATcx8dQXZqcmmwlc0b?p=catalogue 整个源代码: http : //plnkr.co/edit/suATcx8dQXZqcmmwlc0b?p=catalogue

Edit 2: The problem is partially solved. 编辑2:问题已部分解决。 I added this filter functionality: 我添加了此过滤器功能:

 <div class="post" data-ng-repeat="post in postList | bytitle : filterTerm">

but something goes wrong while running the script: 但是运行脚本时出了点问题:

TypeError: Cannot read property 'length' of undefined

It occurs at line 7 (the one with posts.length ). 它发生在第7行(带有posts.length )。

EDIT 编辑

I didn't see the answer from @grundy before making my comments or edits, so it should be accepted as the answer, but I wanted to point out two things: 在进行评论或编辑之前,我没有从@grundy看到答案,因此应该接受它作为答案,但我想指出两点:

Working Plunker 工作柱塞

My preferred approach is to use the angular.isDefined / angular.isArray: 我的首选方法是使用angular.isDefined / angular.isArray:

angular.module("blog").
  filter('bytitle', function() {
    return function(posts, title) {
      if(angular.isDefined(title) && angular.isArray(posts)) {
        var out = [];
        // Filter logic here, adding matches to the out var.
        var i;
        for(i = 0; i < posts.length; i++){
            if(posts[i].title.indexOf(title) >=0){
              out.push(posts[i]);
            }
        }
        return out;
      } else {
        return posts;
      }
   }
});

Second, I just wanted to point out that while writing your own filters is sometimes necessary and certainly a great skill to master, the easiest way to filter on a single property is to use the built in filter filter by adding the property to the model value that you want to search on: 其次,我只想指出,虽然有时需要编写自己的过滤器,并且一定要掌握一定的技巧,但对单个属性进行过滤的最简单方法是通过将内置属性添加到模型值中来使用内置过滤器您要搜索的:

<input data-ng-model="filterTerm.title" />
<input data-ng-model="filterTerm.text" /> 

and then in your repeat add the filter using just the object name as follows: 然后重复使用对象名称添加过滤器,如下所示:

<div class="post" data-ng-repeat="post in postList | filter: filterTerm ">

You can then use the same filter for multiple properties. 然后,您可以将同一过滤器用于多个属性。

in you file with filters instead angular.module("blog", []) you need angular.module("blog") . 在带有过滤器的文件中,而不是angular.module("blog", [])您需要angular.module("blog")
in first case - you create module in second - get. 在第一种情况下-您在第二个模块中创建-获取。

see doc : 文档

When passed two or more arguments, a new module is created. 当传递两个或多个参数时,将创建一个新模块。 If passed only one argument, an existing module (the name passed as the first argument to module) is retrieved. 如果仅传递一个参数,则将检索现有模块(作为第一个参数传递给模块的名称)。

sidenote: in plunker you have wrong reference to js files 旁注:在插件中,您对js文件的引用有误

You have error with length property, because before loading posts by ajax, you not init this variables, so in filter passed undefined . 您有length属性错误,因为在通过ajax加载帖子之前,您没有初始化此变量,因此在filter中传递了undefined

You can modify your filter like 您可以像这样修改过滤器

angular.module("blog").
filter('bytitle', function() {
  return function(posts, title) {
    var out = [];

    //if not pass posts - return empty
    if(!posts) return out;

    //if not pass title, or it empty - return same collection
    if(!title) return posts;

    // Filter logic here, adding matches to the out var.
    var i;
    for (i = 0; i < posts.length; i++) {
      if (posts[i].title.indexOf(title) >= 0) {
        out.push(posts[i]);
      }
    }
    return out;
  }
});

 var app = angular.module("blog", []); app.controller("postController", function($scope, $http, $timeout) { var path = 'http://private-79b25-blogtt.apiary-mock.com'; $scope.titleFilter = ""; $scope.contentFilter = ""; $http.get(path + '/posts') .success(function(data, status, headers, config) { $timeout(function() { $scope.postList = data; }); }) .error(function(data, status, headers, config) { console.log("error getting " + status); }); $scope.form_header = "New post"; $scope.addPost = function() { var post = { title: $scope.title, text: $scope.text, published_at: new Date() }; $http.post(path + '/posts', post) .success(function(data, status, headers, config) { $scope.postList.push(post); }) .error(function(data, status, headers, config) { console.log("error posting " + status); }); $scope.title = ""; $scope.text = ""; }; $scope.deletePost = function(post) { var del = confirm("Are you sure you want to delete or modify this post?"); if (del) { var i = $scope.postList.indexOf(post); $scope.postList.splice(i, 1); } }; var backupPostContent; $scope.editPost = function(post) { $scope.deletePost(post); $scope.form_header = "Edit post"; $scope.title = post.title; $scope.text = post.text; backupPostContent = post; }; $scope.cancelEdit = function() { $http.post(path + '/posts', backupPostContent) .success(function(data, status, headers, config) { $scope.postList.push(backupPostContent); $scope.form_header = "New post"; }) .error(function(data, status, headers, config) { console.log("error posting " + status); }); $scope.title = ""; $scope.text = ""; }; $scope.filter = function(term) { } }); angular.module("blog"). filter('bytitle', function() { return function(posts, title) { var out = []; if(!posts) return out; if(!title) return posts; // Filter logic here, adding matches to the out var. var i; for (i = 0; i < posts.length; i++) { if (posts[i].title.indexOf(title) >= 0) { out.push(posts[i]); } } return out; } }); 
 #wrap { width: 600px; margin: 0 auto; } #left_col { float: left; width: 300px; } #right_col { float: right; width: 300px; } body { padding: 0px 15px; } .row-centered { text-align: right; } .page-header { background-color: #cb892c; margin-top: 0; padding: 20px 20px 20px 40px; } .page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active { color: #ffffff; font-size: 36pt; text-decoration: none; } .content { margin-left: 40px; } h1, h2, h3, h4 { font-family: Helvetica, sans-serif; } .date { float: right; color: #828282; } .save { float: right; } .post-form textarea, .post-form input { width: 60%; } .top-menu, .top-menu:hover, .top-menu:visited { color: #ffffff; float: right; font-size: 26pt; margin-right: 20px; } .post { margin-bottom: 70px; } .post h1 a, .post h1 a:visited { color: #000000; } 
 <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css" rel="stylesheet" /> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet" /> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <div ng-app="blog" ng-controller="postController"> <div id="wrap"> <div id="left_col"> <h3> Search </h3> <p> <input data-ng-model="filterTerm" /> </p> </div> <div id="right_col"> <div id="wrap"> <div id="left_col"> <input type="checkbox" value="topic" id="title" ng-model="titleFilter" />In topics <br> <input type="checkbox" value="content" id="content" />In contents <br> <input type="checkbox" value="content" id="content" />In tags <br>Between <input type="text" type="text" class="datepicker" /> </div> <div id="right_col"> <br> <br> <br>and <input type="text" type="text" class="datepicker" /> <br/> </div> </div> </div> </div> <div class="content container" style="padding-top: 50px"> <div class="row"> <div class="col-md-8 col-centered"> <div class="post" data-ng-repeat="post in postList | bytitle : filterTerm "> <div class="date">published: {{post.published_at | date:'dd-MM-yyyy, HH:mm'}}</div> <a class="btn btn-default" data-ng-click="editPost(post)"><span class="glyphicon glyphicon-pencil"></span></a> <a class="btn btn-default" data-ng-click="deletePost(post)"><span class="glyphicon glyphicon-remove"></span></a> <h1><a href="">{{post.title}}</a></h1> <p>{{post.text}}</p> </div> </div> <div class="col-md-4 col-centered"> <h1>New post</h1> <form class="post-form"> <h4>Title:</h4> <p> <input type="text" name="title" data-ng-model="title"> </p> <h4>Text:</h4> <p> <textarea name="text" data-ng-model="text"></textarea> </p> <button type="submit" class="save btn btn-default" ng-click="addPost()">Save</button> <button type="reset" class="btn btn-default">Clear</button> <button type="button" class="btn btn-default" ng-click="cancelEdit()">Cancel edit</button> </form> </div> </div> </div> </div> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM