Julian Blair Julian Blair - 10 months ago 94
HTML Question

want to pass ng-repeat object to custom filter function


A user should be able to type into the search field the name of a course, and see a list of students who are registered on that course.


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


ng-repeat through a list of student objects. For each student object, pass object to a custom filter function
filterByCourse(byCourse, student)

To be implemented: filterByCourse function iterates through student.courses. If a course with the same name or code as byCourse is found, this is added to a list of filteredStudents. pass the filteredStudents list to the view in place of the unfiltered list of students.

Here's the code:

<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]"

<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>
<p class="student_nr">{{ student._id }}</p>

The Problem:

When I pass the student object into filterByCourse, a console.log on the first line shows that student is undefined, so I can't iterate through the courses and return a list of filtered students as I'd like to.

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

Things I've tried:

  • I've tried to use the filter function in the ng-repeat to iterate through each student object's course list but cannot figure out how to do it.

  • I've tried hitting things with hammers.

Further problem:

I only wish to filter the results in this way if the user has entered some string into the input field. If the input field is empty the filter function should not be triggered. I have no idea how to do this bit!


What you are trying to create is called a predicate function. You can read up on it here(just scroll to function(value, index, array))

Please see working example here

If you type in "course" you will see both students, if you type "course1" you will only see the first student. The same counts for the course code "CC1"

A predicate function can be used to write arbitrary filters. The function is called for each element of the array, with the element, its index, and the entire array itself as arguments.

The final result is an array of those elements that the predicate returned true for


<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 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">


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) {
      return course.courseName.toLowerCase().indexOf($scope.studentFilter.toLowerCase()) > -1 || course.courseCode.toLowerCase().indexOf($scope.studentFilter.toLowerCase()) > -1;
    }).length > 0;