【问题标题】:Filtering directive in Angular.jsAngular.js 中的过滤指令
【发布时间】:2015-07-29 07:59:15
【问题描述】:

我正在尝试开发一个单独的 Web 应用程序,它是一个博客,用于显示帖子。它们被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>      

它们具有在控制器中定义的字段,例如标题、文本和发布日期。我想按各种标准过滤它们。为此,我尝试实现自己的自定义过滤器(这样我就可以过滤多个字段):

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

但是,如果我运行 javascript 控制台,我会收到以下错误,这仅是由于上述代码的存在引起的:

Argument 'postController' is not a function, got undefined

我是 angular 的新手,我不太确定这意味着什么。有什么想法吗?

完整源码:http://plnkr.co/edit/suATcx8dQXZqcmmwlc0b?p=catalogue

编辑 2:问题已部分解决。我添加了这个过滤器功能:

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

但是在运行脚本时出了点问题:

TypeError: Cannot read property 'length' of undefined

它出现在第 7 行(带有posts.length 的那一行)。

【问题讨论】:

  • 在你的文件中使用过滤器而不是angular.module("blog", []).,你需要angular.module("blog").。在第一种情况下-您在第二种情况下创建模块-获取。参见doc当传递两个或多个参数时,会创建一个新模块。如果只传递一个参数,则检索现有模块(作为第一个参数传递给模块的名称)。
  • 好的,很公平。不过还是有问题,请查看我的修改

标签: javascript angularjs function arguments


【解决方案1】:

编辑

在进行我的 cmets 或编辑之前,我没有看到 @grundy 的答案,所以它应该被接受为答案,但我想指出两点:

Working Plunker

我的首选方法是使用 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;
      }
   }
});

其次,我只是想指出,虽然有时需要编写自己的过滤器,并且掌握一项很棒的技能,但过滤单个属性的最简单方法是使用内置过滤器过滤器,方法是将属性添加到您要搜索的模型值:

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

然后在重复中仅使用对象名称添加过滤器,如下所示:

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

然后您可以对多个属性使用相同的过滤器。

【讨论】:

  • 您能否提供一个 Plunkr,以便我可以在上下文中查看控制器、示例模型和视图以帮助您调试?我在您发布的代码中的任何地方都没有看到 postController,所以我不知道它的来源。
  • 实际上它可能只是一个非常简单的错字,但你已经定义了你的博客模块两次!如果您查看 filters.js 文件并简单地删除作为模块定义的第二个参数的空数组,Angular 将改为查找名为 blog 的现有模块。所以它应该是: angular.module("blog").filter( ... 或者你当然可以这样做: app.filter(...
  • 是的,上面已经指出,更正了。如果您能看到我最近的编辑中发生了什么错误,那就太好了;)
  • 因此过滤器被调整为仅在定义标题时运行,否则仅返回帖子。
【解决方案2】:

在您的文件中使用过滤器而不是 angular.module("blog", []) 您需要 angular.module("blog")
在第一种情况下-您在第二种情况下创建模块-获取。

doc

当传递两个或多个参数时,会创建一个新模块。如果仅传递一个参数,则检索现有模块(作为第一个参数传递给模块的名称)。

旁注: 在 plunker 中您对 js 文件的引用有误

length 属性有错误,因为在通过 ajax 加载帖子之前,你没有初始化这个变量,所以在过滤器中传递了 undefined

你可以修改你的过滤器

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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-23
    相关资源
    最近更新 更多