JoCa JoCa - 6 months ago 13
Javascript Question

Custom filter on 'ng-repeat' does overwrite the scope

My aim is to replace the teacher-id(f_teacher) of one outputted array with the teacher name of another array. I wrote a custom filter, that should do the job:

.filter('replaceId', function () { //filter, which replaces Id's of one array, with corresponding content of another array
return function (t_D, s_D, t_prop, s_prop) { //data of target, data of source, target property, source property
var replacment = {};
var output = [];
angular.forEach(s_D, function (item) {
replacment[] = item[s_prop]; //replacment - object is filled with 'id' as key and corresponding value
angular.forEach(t_D, function (item) {
item[t_prop] = replacment[item[t_prop]]; //ids of target data are replaced with matching value
return output;

I use a 'ng-repeat' like this:

<tr ng-repeat="class in $ctrl.classes | filter:$ | replaceId:$ctrl.teachers:'f_teacher':'prename' | orderBy:sortType:sortReverse">

But it only outputs an empty column. Now the strange thing: If I follow the steps with the debugger, it works for the first time the filter is performed. But when it is performed a second time it outputs an empty column.

I noticed that the returned object of the filter overwrites the $ctrl.classes - array, but normally this shouldn't be the case?

Here is a plnkr:

Why is this happening?

Thank you for your time :)

rob rob

The first time through your filter the code takes the f_teacher id and replaces it with the teacher name. The second time through it tries to do the same thing except now instead of getting a teachers ID in f_teacher it finds the teacher's name so it doesn't work. You could fix it by making a copy of the classes instead of modifying them directly. e.g.

angular.forEach(t_D, function (item) {
    var itemCopy = angular.copy(item);
    itemCopy[t_prop] = replacment[itemCopy[t_prop]];


Original solution will trigger an infinite digest because the filter returns new instances of objects every time it runs which will cause angular to think something has changed and retrigger a digest. Could you just have a getter function that gets a teachers name instead of using a filter?

$scope.getTeacherName = function(id) {
  var matchingTeachers = $scope.teachers.filter(function(teacher) {
    return == id;

  //Should always be exactly 1 match.
  return matchingTeachers[0].prename;

And then in the HTML you could use it like

<tr ng-repeat="class in classes">