0

这是一个笨蛋:

http://plnkr.co/edit/hJsZFCBZhFT5rRo1lgSZ?p=preview

这是一个简单的指令,应该显示给定数量的点,并根据给定的值、最小值和最大值突出显示它们的子集,类似于星级。它单独工作时效果很好(正如您在 plunkr 的最后一行中看到的那样),但在 ngRepeat 中却不行。问题是指令自己的 ngRepeat 上的 ngClass 似乎失败了,即使 ngClass 中使用的表达式似乎在 ngClass 之外正确评估。在过去的几个小时里,我一直在为此扯头发,我就是想不通。

这是实际的代码:

HTML:

<div ng-repeat="row in [1,2,3,4,5]">
  <match-dots value="{{ $index+1 }}" min="0" max="10">{{ isDotActive($index) }}</match-dots>
</div>

JS:

angular.module('app', [])
.directive('matchDots', function() {
    return {
        restrict: 'EA',
        replace: true,
        transclude: true,
        template:
            "<span class='match-dots-group'>" +
              "<span class='match-dots-dot' ng-repeat='dot in dotsList()' ng-class='{ active: isDotActive($index) }' ng-transclude></span>" +
            "</span>",
        scope: {
            dots: '@',
            min: '@',
            max: '@',
            value: '@'
        },
        link: function(scope, elem) {
            // save the previous class applied so we can remove it when the class changes
            var previousClass = '';

            /**
             * set the class for the dots-group based on how many dots are active (n-active)
             */
            scope.setDotsClass = function() {
                if(previousClass != '') {
                    elem.removeClass(previousClass);
                }
                previousClass = "active-"+scope.numActiveDots();
                elem.addClass(previousClass);
            }
        },
        controller: function($scope) {

            $scope.dots = angular.isUndefined($scope.dots)?5:parseInt($scope.dots);
            $scope.min = angular.isUndefined($scope.min)?0:parseInt($scope.min);
            $scope.max = angular.isUndefined($scope.max)?100:parseInt($scope.max);

            /**
             * create a list of numbers
             * @returns {Array}
             */
            $scope.dotsList = function() {
                var arr = [];
                for(var i=1; i<=$scope.dots; i++) {
                    arr.push(i);
                }
                return arr;
            };

            /**
             * should the given dot be lit up?
             * @param {number} dot
             * @returns {boolean}
             */
            $scope.isDotActive = function(dot) {
                return dot < $scope.numActiveDots();
            };

            /**
             * How many dots are active?
             * @returns {number}
             */
            $scope.numActiveDots = function() {
                var activeDots = Math.ceil(($scope.value-$scope.min) / (($scope.max-$scope.min) / $scope.dots));
                return isNaN(activeDots)?0:activeDots;
            };

            // make sure the value is an number
            $scope.$watch('value', function(newValue) {
                $scope.value = parseFloat(newValue);
                $scope.setDotsClass();
            });

            // make sure the number of dots is actually a positive integer
            $scope.$watch('dots', function(newDots) {
                if(angular.isUndefined(newDots) || !newDots || newDots < 1) {
                    $scope.dots = 5;
                } else {
                    $scope.dots = parseInt(newDots);
                }
                $scope.setDotsClass();
            });

            // make sure the min is not greater than the max
            $scope.$watch('max', function(newMax) {
                if(angular.isUndefined(newMax)) {
                    $scope.max = newMax = 100;
                }
                if(angular.isString(newMax)) {
                    $scope.max = parseFloat(newMax);
                } else if(newMax < $scope.min) {
                    $scope.max = $scope.min;
                    $scope.min = newMax;
                }
                $scope.setDotsClass();
            });

            // make sure the max is not less than the min
            $scope.$watch('min', function(newMin) {
                if(angular.isUndefined(newMin)) {
                    $scope.min = newMin = 0;
                }
                if(angular.isString(newMin)) {
                    $scope.min = parseFloat(newMin);
                } else if(newMin > $scope.max) {
                    $scope.min = $scope.max;
                    $scope.max = newMin;
                }
                $scope.setDotsClass();
            });
        }
    }
});
4

1 回答 1

0

对我来说看起来可疑的第一件事是您正在重新分配 $scope.dots 属性和您的 numActiveDots 函数,通常以 NaN 结束。该属性作为字符串传递到您的指令中,然后您将其解析/重新分配为数字。我尝试将您的解析值重命名为 $scope.dotsinternal。这似乎使它起作用。

http://plnkr.co/edit/STwuts2D169iBLDoTtE2?p=preview

改变这个:

$scope.dots = angular.isUndefined($scope.dots)?5:parseInt($scope.dots);

对此:

$scope.dotsinternal = angular.isUndefined($scope.dots)?5:parseInt($scope.dots);

然后将所有对 $scope.dots 的引用更新为 $scope.dotsinternal。

于 2014-02-05T22:50:52.060 回答