简体   繁体   English

'ng-repeat'上的自定义过滤器会覆盖范围

[英]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. 我的目标是将一个输出数组的教师ID(f_teacher)替换为另一数组的教师名称。 I wrote a custom filter, that should do the job: 我写了一个自定义过滤器,应该可以完成这项工作:

angular.module('core')
.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.id] = 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
            output.push(item);
        });
        return output;
    }
});

I use a 'ng-repeat' like this: 我使用这样的“ ng-repeat”:

<tr ng-repeat="class in $ctrl.classes | filter:$ctrl.search | replaceId:$ctrl.teachers:'f_teacher':'prename' | orderBy:sortType:sortReverse">
    <td>{{class.level}}</td>
    <td>{{class.classNR}}</td>
    <td>{{class.f_teacher}}</td>
</tr>

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? 我注意到过滤器返回的对象覆盖了$ ctrl.classes-数组,但是通常情况并非如此吗?

Here is a plnkr: https://plnkr.co/edit/EiW59gbcLI5XmHCS6dIs?p=preview 这是一个plnkr: https ://plnkr.co/edit/EiW59gbcLI5XmHCS6dIs ? p = preview

Why is this happening? 为什么会这样呢?

Thank you for your time :) 感谢您的时间 :)

The first time through your filter the code takes the f_teacher id and replaces it with the teacher name. 第一次通过过滤器,代码将使用f_teacher id并将其替换为教师姓名。 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. 它第二次尝试执行相同的操作,只是现在不是在f_teacher中获取教师ID,而是找到教师的姓名,因此它不起作用。 You could fix it by making a copy of the classes instead of modifying them directly. 您可以通过复制类而不是直接修改它们来修复它。 eg 例如

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

https://plnkr.co/edit/RDvBGITSAis3da6sWnyi?p=preview https://plnkr.co/edit/RDvBGITSAis3da6sWnyi?p=preview

EDIT 编辑

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. 原始解决方案将触发一个无限摘要,因为过滤器每次运行时都会返回对象的新实例,这将导致angular认为某些内容已更改并重新触发摘要。 Could you just have a getter function that gets a teachers name instead of using a filter? 您能否仅使用获取教师姓名的getter函数,而不使用过滤器?

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

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

And then in the HTML you could use it like 然后在HTML中,您可以像

<tr ng-repeat="class in classes">
  <td>{{class.level}}</td>
  <td>{{class.classNR}}</td>
  <td>{{getTeacherName(class.f_teacher)}}</td>
</tr>

https://plnkr.co/edit/gtu03gQHlRIMsh9vxr1c?p=preview https://plnkr.co/edit/gtu03gQHlRIMsh9vxr1c?p=preview

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM