想要将ng-repeat对象传递给自定义过滤器函数

时间:2016-05-05 13:06:16

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

目的:

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

型号:

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

方式:

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

要实现: filterByCourse函数遍历student.courses。如果找到与byCourse具有相同名称或代码的课程,则会将其添加到filteredStudents列表中。将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-->

问题:

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

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

我尝试过的事情:

  • 我尝试在ng-repeat中使用过滤功能来遍历每个学生对象的课程列表,但无法弄清楚如何去做。

  • 我试过用锤子击打东西。

更多问题:

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

2 个答案:

答案 0 :(得分:3)

功能

filterByCourse

只能在&#39; byCourse&#39;在html中,它的实现应该只接收参数&#39; byCourse&#39;。此函数还应该返回一个接收学生对象的函数。 所以你应该

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

并且在javascript中它应该是

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

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

答案 1 :(得分:2)

选项1

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

  

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

     

最终结果是谓词为

返回true的那些元素的数组

请参阅工作示例here

如果您输入&#34;课程&#34;你会看到两个学生,如果你输入&#34; course1&#34;你只会看到第一个学生。课程代码&#34; CC1&#34;

的计数相同

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(滚动到对象:模式ob ...),请参阅工作示例here

  

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

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