2016-05-05 3 views
2

Ziel weitergeben müssen:wollen ng-repeat Objekt angepasste Filterfunktion

Ein Benutzer in das Suchfeld eingeben sollte in der Lage, den Namen eines Kurses, und eine Liste von Studenten sehen, die auf dem registriert sind, Kurs.

Modelle:

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

Methode:

ng-Repeat durch eine Liste von Studenten Objekte. Übergeben Sie für jedes Schülerobjekt Objekt an eine benutzerdefinierte Filterfunktion filterByCourse(byCourse, student).

Implementiert werden: filterByCourse-Funktion iteriert durch student.courses. Wenn ein Kurs mit dem gleichen Namen oder Code wie von Course gefunden wird, wird dieser zu einer Liste von filteredStudents hinzugefügt. Übergeben Sie die filteredStudents-Liste an die Stelle der ungefilterten Schülerliste.

Hier ist der 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]" 
      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--> 

Das Problem:

Wenn ich die Schüler Objekt in filterByCourse, ein console.log in der ersten Zeile passieren zeigt, dass Schüler nicht definiert ist, so Ich kann nicht durch die Kurse iterieren und gebe eine Liste von gefilterten Studenten zurück, wie ich möchte.

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

Dinge, die ich habe versucht:

  • Ich habe versucht, die Filterfunktion in der ng-repeat zu verwenden, um durch jeden Schüler Objekt Kursliste iterieren kann aber nicht herausfinden, wie man TU es.

  • Ich habe versucht, Dinge mit Hämmern zu schlagen.

Weiteres Problem:

Ich möchte nur die Ergebnisse auf diese Weise filtern, wenn der Benutzer eine Zeichenfolge in das Eingabefeld eingegeben hat. Wenn das Eingabefeld leer ist, sollte die Filterfunktion nicht ausgelöst werden. Ich habe keine Ahnung, wie ich das mache!

+0

zeigen Sie bitte Ihre Filterfunktion, da wir kann nicht sehen, was los ist, ohne zu zeigen, wie Sie es implementiert haben.Vielleicht ist es sowieso besser, einen benutzerdefinierten Filter zu erstellen, anstatt eine Funktion mit der eingebauten Angular-Filterfunktion aufzurufen. –

+0

@pkeuter die benutzerdefinierte Filterfunktion ist noch nicht implementiert. Alles, was es bis jetzt macht, ist console.log student, das nicht definiert ist, wenn die Funktion von veiw aufgerufen wird. Das ist das erste Problem:/ –

+0

Ich verstehe, dass es noch nicht vollständig implementiert ist, aber Sie haben begonnen, es zu implementieren, und erhalten eine Fehlermeldung in dieser Funktion. Bitte zeigen Sie es, damit wir sehen können, was Sie hier vorhaben. –

Antwort

2

Option 1:

Was Sie versuchen, ein Prädikat Funktion aufgerufen zu erstellen ist. Sie können bis auf es here (nur blättern zu function(value, index, array)) lesen

Ein Prädikat Funktion kann verwendet werden, um beliebige Filter zu schreiben. Die Funktion wird für jedes Element des Arrays mit dem Element, seinem Index und dem gesamten Array selbst als Argumente aufgerufen.

Das Endergebnis ist eine Anordnung dieser Elemente, daß das Prädikat sehen für

Bitte Arbeitsbeispiel true zurückgegeben here

Wenn Sie geben in „Kurs“ Sie werden beide Studenten sehen, wenn Sie eingeben "course1" werden Sie nur den ersten Schüler sehen. Das Gleiche gilt für den Kurs Code "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; 
    }; 
}]); 

Option 2

Sie ein Objekt als filter expression (scroll verwenden können zu Objekt: Ein Muster ob ...), siehe Arbeitsbeispiel here

Ein Musterobjekt kann zum Filtern bestimmter Eigenschaften von Objekten verwendet werden, die in einem Array enthalten sind. Zum Beispiel liefert das {Prädikat {Name: "M", Telefon: "1"} ein Array von Elementen, deren Eigenschaftsname "M" und Eigenschaftstelefon mit "1" enthält. Ein spezieller Eigenschaftsname $ kann verwendet werden (wie in {$: "text"}), um eine Übereinstimmung mit einer Eigenschaft des Objekts oder seinen verschachtelten Objekteigenschaften zu akzeptieren. Das entspricht der einfachen Teilzeichenfolge, die mit einer Zeichenfolge wie oben beschrieben übereinstimmt. Das Prädikat kann negiert werden, indem der Zeichenfolge ein Präfix vorangestellt wird. Zum Beispiel liefert das {Name: "! M"} - Prädikat ein Array von Elementen, deren Eigenschaftenname kein "M" enthält.

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

Wenn keine benutzerdefinierten Code oder erweiterte Filterung erforderlich ist, entscheide ich mich für Option 2

+0

Das hat wunderbar funktioniert! Eine Frage - funktioniert die letzte Zeile .length> 0 als eine Art Bedingung? Also wird nur zurückgegeben, wenn die Länge größer als 0 ist? Große Antwort! –

+0

'.length' gibt die Länge der gefilterten Kurse für den aktuellen Schüler in der Iteration zurück, wir wollen nur Schüler sehen, bei denen sie passende Kurse aufgelistet haben und deshalb geben wir' .length> 0' –

+0

Ich weiß was die Längeneigenschaft ist für, aber ich frage, ob "Länge> 0;" ist wie eine Bedingung, die wahr zurückgibt, wenn die Länge größer als 0 und falsch ist, wenn sie nicht größer als 0 ist? Ziemlich sicher, das ist was los ist. –

2

Die Funktion

filterByCourse 

sollte nur mit 'byCourse' in dem HTML-Code, und es ist die Umsetzung soll nur erhält die Parameter 'byCourse' bezeichnet werden. Diese Funktion sollte auch eine Funktion zurückgeben, die ein Schülerobjekt empfängt. so sind Sie html

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

und in der JavaScript sollte es sollte

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

sein (die Funktion, dass der Filter kehrt Zugriff auf den byCourse Parameter Cuz seine im gleichen Kontext haben würde) . hier ist eine Arbeits jsFiddle