【问题标题】:want to pass ng-repeat object to custom filter function想将 ng-repeat 对象传递给自定义过滤器函数
【发布时间】:2016-08-31 06:58:41
【问题描述】:

目标:

用户应该能够在搜索字段中输入课程名称,并查看已注册该课程的学生列表。

型号:

course (has a course name and course code)
student (has a list of registered courses)
students (an array of student objects)

方法:

ng-repeat 遍历学生对象列表。对于每个学生对象,将对象传递给自定义过滤函数filterByCourse(byCourse, student)

待实现: filterByCourse 函数遍历 student.courses。如果找到与 byCourse 具有相同名称或代码的课程,则会将其添加到过滤学生列表中。将filteredStudents 列表传递给视图以代替未过滤的学生列表。

代码如下:

<input class="form-control" type="text" ng-model="byCourse"
placeholder="Search by course id or course name..">

<ul ng-repeat="student in students | filter: filterByCourse(byCourse, student)">
        <li ng-init="index=0; classes=['list--students_item', 'list--students_item--active']" ng-click="stageMeToCourse($index)" 
            ng-class="classes[index % classes.length]" 
            class="col-xs-24">

            <img src="/img/profile_default.png">
            <h4>{{ student.first_name }} {{ student.last_name }} 
                <span class="role">{{ student.role }}</span>
                <i class="fa fa-chevron-right"></i>
            </h4>
            <p class="student_nr">{{ student._id }}</p>
        </li>
    </ul>
</div><!--list-students-->

问题:

当我将学生对象传递给 filterByCourse 时,第一行的 console.log 显示学生未定义,因此我无法遍历课程并返回我想要的过滤学生列表。

scope.filterByCourse = function(course, student){
    console.log(student); //student is undefined
}

我尝试过的事情:

  • 我尝试使用 ng-repeat 中的过滤器功能来遍历每个学生对象的课程列表,但不知道该怎么做。

  • 我试过用锤子敲东西。

进一步的问题:

如果用户在输入字段中输入了一些字符串,我只希望以这种方式过滤结果。如果输入字段为空,则不应触发过滤功能。我不知道该怎么做!

【问题讨论】:

  • 请展示您的过滤功能,因为如果不展示您的实现方式,我们将无法看到问题所在。也许最好还是创建一个自定义过滤器,而不是使用内置的 Angular 过滤器函数调用函数。
  • @pkeuter 自定义过滤功能还没有实现。到目前为止,它所做的只是 console.log student,当从 veiw 调用函数时,它是未定义的。这是第一个问题:/
  • 我知道它还没有完全实现,但是您已经开始实现它并且在该函数中收到一条错误消息。请出示它,以便我们可以看到您在此处尝试执行的操作。
  • @JulianBlair 请查看选项 2 的更新答案

标签: javascript html angularjs angularjs-ng-repeat ng-repeat


【解决方案1】:

功能

filterByCourse

应该只在html中使用'byCourse'调用,并且它的实现应该只接收参数'byCourse'。此函数还应该返回一个函数,它接收一个学生对象。 所以你的html应该是

<ul ng-repeat="student in students | filter: filterByCourse(byCourse)">

在 javascript 中应该是

$scope.filterByCourse = function (byCourse) {
  return function (student) {
      console.log(student);
  }
};

(过滤器返回的函数可以访问 byCourse 参数,因为它在相同的上下文中)。 这是一个有效的jsFiddle

【讨论】:

    【解决方案2】:

    选项 1

    您尝试创建的内容称为谓词函数。你可以阅读它here(只需滚动到function(value, index, array)

    谓词函数可用于编写任意过滤器。为数组的每个元素调用该函数,将元素、其索引和整个数组本身作为参数。

    最终结果是谓词返回 true 的那些元素的数组

    请参阅工作示例here

    如果您输入“course”,您将看到两个学生,如果您输入“course1”,您将只看到第一个学生。课程代码“CC1”也一样

    HTML:

    <div ng-controller="TestController" class="panel panel-primary">
      <form class="form-inline">
        <div class="form-group">
          <input type="text" class="form-control" placeholder="Filter" ng-model="studentFilter">
        </div>
      </form>
      <div class="panel-heading">Students</div>
        <ul class="list-group">
          <li class="list-group-item" ng-repeat="student in students | filter:onFilterStudents">
          {{student.firstName}} {{student.surname}}
            <ul class="list-group">
              <li class="list-group-item" ng-repeat="course in student.courses">
                {{course.courseName}}-{{course.courseCode}}
              </li>
            </ul>
         </li>
      </ul>
    </div>
    

    JS:

    var myApp = angular.module('myApp', []);
    
    myApp.controller('TestController', ['$scope', function($scope) {
      $scope.students = [{
        firstName: 'John',
        surname: 'Doe',
        courses: [{
          courseName: 'course1',
          courseCode: 'CC1'
        }, {
          courseName: 'course2',
          courseCode: 'CC7'
        }]
      }, {
        firstName: 'Jane',
        surname: 'Doe',
        courses: [{
          courseName: 'course3',
          courseCode: 'CC2'
        }, {
          courseName: 'course4',
          courseCode: 'CC3'
        }]
      }];
    
      $scope.onFilterStudents = function(value, index, array) {
        if ($scope.studentFilter === '' || $scope.studentFilter === null || $scope.studentFilter === undefined) {
          return true;
        }    
        return value.courses.filter(function(course) {
        console.log(course);
          return course.courseName.toLowerCase().indexOf($scope.studentFilter.toLowerCase()) > -1 || course.courseCode.toLowerCase().indexOf($scope.studentFilter.toLowerCase()) > -1;
        }).length > 0;
      };
    }]);
    

    选项 2

    您可以将对象用作filter expression(滚动到对象:模式对象...),请参阅工作示例here

    模式对象可用于过滤数组包含的对象的特定属性。例如 {name:"M", phone:"1"} 谓词将返回一个项目数组,这些项目的属性名称包含“M”,属性电话包含“1”。可以使用特殊的属性名称 $(如在 {$:"text"} 中)接受与对象的任何属性或其嵌套对象属性的匹配。这相当于上面描述的与字符串的简单子字符串匹配。谓词可以通过在字符串前面加上 ! 来否定。例如 {name: "!M"} 谓词将返回属性名称不包含 "M" 的项目数组。

    HTML:

    <div ng-controller="TestController" class="panel panel-primary">
      <form class="form-inline">
        <div class="form-group">
          <input type="text" class="form-control" placeholder="Filter" ng-model="studentFilter">
        </div>
      </form>
      <div class="panel-heading">Students</div>
      <ul class="list-group">
        <li class="list-group-item" ng-repeat="student in students | filter:{courses:{$:studentFilter}}">
          {{student.firstName}} {{student.surname}}
          <ul class="list-group">
            <li class="list-group-item" ng-repeat="course in student.courses">
              {{course.courseName}}-{{course.courseCode}}
            </li>
          </ul>
        </li>
      </ul>
    </div>
    

    JS:

    var myApp = angular.module('myApp', []);
    
    myApp.controller('TestController', ['$scope', function($scope) {
      $scope.students = [{
        firstName: 'John',
        surname: 'Doe',
        courses: [{
          courseName: 'course1',
          courseCode: 'CC1'
        }, {
          courseName: 'course2',
          courseCode: 'CC7'
        }]
      }, {
        firstName: 'Jane',
        surname: 'Doe',
        courses: [{
          courseName: 'course3',
          courseCode: 'CC2'
        }, {
          courseName: 'course4',
          courseCode: 'CC3'
        }]
      }];  
    }]);
    

    如果不需要自定义代码或高级过滤,我选择选项 2

    【讨论】:

    • 这很棒!一个问题 - 最后一行 .length > 0 是否作为一种条件起作用?所以它只有在长度大于0时才返回?很好的答案!
    • .length 返回迭代中当前学生的过滤课程长度,我们只想查看列出匹配课程的学生,这就是为什么我们返回.length&gt;0
    • 我知道长度属性的用途,但我问的是“长度 > 0;”是否就像一个条件,如果长度大于 0,则返回 true,如果不大于 0,则返回 false?很确定这是怎么回事..
    猜你喜欢
    • 2016-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-09
    • 1970-01-01
    • 1970-01-01
    • 2017-06-11
    相关资源
    最近更新 更多