如何从ng-repeat表达式中更新父范围变量?

时间:2021-08-13 02:41:16

I've run into a situation where I had to update a scope variable from within an ng-repeat expression (ng-class call within ng-repeat in fact).

我遇到过这样一种情况:我必须从ng-repeat表达式中更新范围变量(事实上在ng-repeat中的ng-class调用)。

<div id="page" ng-controller="MainCtrl">
.
 <section id="body" ng-init="countMis = {num:0}">
.
<tbody>
  <tr ng-repeat="upperCaseLetter in alphabet.specialsUpper" ng-controller="letterController">
    <td>{{upperCaseLetter}}</td>
    <td>{{filteredLetter=(upperCaseLetter | lowercase)}}</td>
    <td>{{alphabet.specialsLower[$index]}}</td>
    <td><span ng-class="lowercaseEqual($index,filteredLetter)"></span></td>
  </tr>
</tbody>

and in app.js:

在app.js中:

function letterController($scope)
{
    $scope.lowercaseEqual = function(indx,letter)
    {       
        var returnStr="";

        if(letter == $scope.alphabet.specialsLower[indx])
        {
             returnStr = "glyphicon glyphicon-ok";
        }
        else
        {   
            $scope.countMis.num = $scope.countMis.num + 1;
            returnStr = "glyphicon glyphicon-remove";
        }

        return returnStr;
    };

}

如何从ng-repeat表达式中更新父范围变量?

Ng-repeat is in a child controller and data I want to update is in its parent controller. I know you've read same question many times, please keep reading and see JsFiddle example.

Ng-repeat位于子控制器中,我想要更新的数据位于其父控制器中。我知道你多次读过同样的问题,请继续阅读,看看JsFiddle的例子。

So expression function checks filtered data of that particular ng-repeat iteration, if it doesn't match with some other corresponding parent scope variable it returns a class but also it should update parent scope counter. As those expressions don't evaluate just once, but at least once (because of dirty check in digest) it results counter being incremented more than once for each case.

因此表达式函数检查特定ng-repeat迭代的过滤数据,如果它与其他一些相应的父范围变量不匹配,则它返回一个类,但它也应该更新父范围计数器。由于这些表达式不仅仅评估一次,而是至少一次(因为对摘要进行脏检查),因此对于每种情况,结果计数器增加不止一次。

I've solved my problem by counting classes applied to that particular data after ng-repeat (you'll see in the JsFiddle example). However I think I may run into same problem in the future, so I want to learn how to update parent scope within an expression of ng-repeat iteration.

我通过在ng-repeat之后计算应用于该特定数据的类来解决我的问题(您将在JsFiddle示例中看到)。但是我想我将来会遇到同样的问题,所以我想学习如何在ng-repeat迭代的表达式中更新父作用域。

I've put a second JsFiddle, I've tried using a factory on both parent controller and child, hoping to update a common variable for both controllers. When I log (consol.log) each iteration and factory method variable, it shows iteration times + 1 (still false value), but it's not reflected on page expression...doesn't make sense at all.

我已经放了第二个JsFiddle,我尝试在父控制器和子控件上使用工厂,希望更新两个控制器的公共变量。当我记录(consol.log)每个迭代和工厂方法变量时,它显示迭代次数+ 1(仍为假值),但它没有反映在页面表达式上......根本没有意义。

I'd appreciate any help. Thanks.

我很感激任何帮助。谢谢。

JsFiddle 1 JsFiddle 2

JsFiddle 1 JsFiddle 2

1 个解决方案

#1


1  

Since watched expressions (like the one implicitely set up by the ng-class directive) "can execute multiple times per $digest() and should be idempotent". You should understand what the $watch() and $digest() functions do and look for resources regarding Angular's digest cycle.

由于监视表达式(如ng-class指令隐含设置的表达式)“每个$ digest()可以执行多次,并且应该是幂等的”。您应该了解$ watch()和$ digest()函数的作用,并查找有关Angular的摘要周期的资源。

So, incrementing a counter inside a watchExpression is not a good idea.
Counting classes seems ok though.

因此,在watchExpression中增加一个计数器并不是一个好主意。计数类似乎没问题。


BTW, the factory-approach will help you share data across scopes, but it won't help with the "multiple executions per digest cycle" problem. Furthermore, it might be redundant in your situation, since the child- and parent-scopes can share data directly.
In any case, for the results to be displayed you have to "bind" the factory's getMismatchCount() function with the getMismatchCount() function that you use in your HTML (in Mismatches Count from Factory: {{getMismatchCount()}}):

顺便说一句,工厂方法将帮助您跨范围共享数据,但它无助于“每个摘要周期的多次执行”问题。此外,在您的情况下可能是多余的,因为子范围和父范围可以直接共享数据。在任何情况下,对于要显示的结果,您必须将工厂的getMismatchCount()函数与您在HTML中使用的getMismatchCount()函数“绑定”(来自工厂的不匹配计数:{{getMismatchCount()}}):

function mainCtrl($scope, $window, repeatFactory)
    ...
    $scope.getMismatchCount = repeatFactory.getMismatchCount;

#1


1  

Since watched expressions (like the one implicitely set up by the ng-class directive) "can execute multiple times per $digest() and should be idempotent". You should understand what the $watch() and $digest() functions do and look for resources regarding Angular's digest cycle.

由于监视表达式(如ng-class指令隐含设置的表达式)“每个$ digest()可以执行多次,并且应该是幂等的”。您应该了解$ watch()和$ digest()函数的作用,并查找有关Angular的摘要周期的资源。

So, incrementing a counter inside a watchExpression is not a good idea.
Counting classes seems ok though.

因此,在watchExpression中增加一个计数器并不是一个好主意。计数类似乎没问题。


BTW, the factory-approach will help you share data across scopes, but it won't help with the "multiple executions per digest cycle" problem. Furthermore, it might be redundant in your situation, since the child- and parent-scopes can share data directly.
In any case, for the results to be displayed you have to "bind" the factory's getMismatchCount() function with the getMismatchCount() function that you use in your HTML (in Mismatches Count from Factory: {{getMismatchCount()}}):

顺便说一句,工厂方法将帮助您跨范围共享数据,但它无助于“每个摘要周期的多次执行”问题。此外,在您的情况下可能是多余的,因为子范围和父范围可以直接共享数据。在任何情况下,对于要显示的结果,您必须将工厂的getMismatchCount()函数与您在HTML中使用的getMismatchCount()函数“绑定”(来自工厂的不匹配计数:{{getMismatchCount()}}):

function mainCtrl($scope, $window, repeatFactory)
    ...
    $scope.getMismatchCount = repeatFactory.getMismatchCount;