AngularJS指令失败,因为$ apply已经在运行

时间:2014-06-08 22:02:23

标签: angularjs angularjs-directive

Error: [$rootScope:inprog] http://errors.angularjs.org/1.2.7/$rootScope/inprog?p0=%apply

嗨!我正在制作一个迷你日历独立指令,而且我无法应用这些月份和日期的变化。它告诉我$ apply已经在进行中,我已经谷歌并且在编译定义对象中使用它时注意到它是一个问题。

但阻止$ apply运行它已经做的事情并没有解决问题,因为它似乎总是在运行。对我的问题的任何建议或修正将不胜感激:D

Controller + Directive

function calendarController($scope) {
    $scope.config = new Date(2013, 4, 25);
}
angular.module("calendar", []).directive('miniCalendar', function($parse) {
    return {
        restrict: "E",
        replace: true,
        templateUrl: "../views/template.html",
        transclude: true,
        controller: function($scope) {
            $scope.currentDate = new Date();
            $scope.prev = function() {
                $scope.mCalDate = new Date($scope.mCalDate.getFullYear(), $scope.mCalDate.getMonth() - 1, $scope.mCalDate.getDay());
                $scope.updateDate($scope.mCalDate);
            };
            $scope.next = function() {
                $scope.mCalDate = new Date($scope.mCalDate.getFullYear(), $scope.mCalDate.getMonth() + 1, $scope.mCalDate.getDay());
                $scope.updateDate($scope.mCalDate);
            };
            $scope.selecting = false;
            $scope.selectDate = function() {
                $scope.selecting = !$scope.selecting;
            };
            $scope.selectDay = function(day) {
                $scope.mCalDate = day.date;
                $scope.updateDate($scope.mCalDate);
            };
            $scope.currentMonth = '';
            $scope.currentYear = '';
            $scope.days = [{
                day: "Sun"
            }, {
                day: "Mon"
            }, {
                day: "Tue"
            }, {
                day: "Wed"
            }, {
                day: "Thu"
            }, {
                day: "Fri"
            }, {
                day: "Sat"
            }];
            $scope.weeks = [];
        },
        scope: {
            mCalDate: '='
        },
        compile: function(element, attrs) {
            var modelAccessor = $parse(attrs.mCalDate);
            return function(scope, element, attrs, controller) {
                scope.currentDate = scope.mCalDate.getDate() + '/' + Math.abs(scope.mCalDate.getMonth() + 1) + '/' + scope.mCalDate.getFullYear();
                var firstDayOfMonth = new Date(scope.mCalDate.getFullYear(), scope.mCalDate.getMonth(), 1).toDateString().split(' ');
                var totalDays = new Date(scope.mCalDate.getFullYear(), scope.mCalDate.getMonth() + 1, 0).getDate();
                var firstDayIndex;
                for (var i in scope.days) {
                    if (scope.days[i].day == firstDayOfMonth[0]) {
                        firstDayIndex = i;
                    }
                }
                var allDays = [];
                var h = 0;
                for (i = 0; i < totalDays + 6; i++) {
                    if (i >= firstDayIndex && (h + 1) <= totalDays) {
                        allDays.push({
                            dayName: scope.days[new Date(scope.mCalDate.getFullYear(), scope.mCalDate.getMonth(), h + 1).getDay()].day,
                            day: ++h,
                            date: new Date(scope.mCalDate.getFullYear(), scope.mCalDate.getMonth(), h + 1)
                        });
                    } else {
                        allDays.push({});
                    }
                }
                var calendar = []
                var chunk = 7;
                for (i = 0, allDays.length; i < allDays.length; i += chunk) {
                    calendar.push({
                        week: calendar.length,
                        days: allDays.slice(i, i + chunk)
                    });
                }
                scope.weeks = calendar;
                scope.currentYear = scope.mCalDate.getFullYear();
                scope.currentMonth = scope.mCalDate.toDateString().split(' ')[1];
                scope.$watch('mCalDate', function(val) {
                    //debugger;
                });
                scope.updateDate = function(date) {
                    scope.mCalDate = date;
                    var phase = scope.$root.$$phase; //Safe applying
                    if (phase != '$apply' || phase != '$digest') {
                        scope.$apply(function() {
                            scope.mCalDate = date;
                            $parse(attrs.mCalDate).assign(scope.$parent, 'config');
                        });
                    }
                };

            };

        }
    };
});

HTML

<mini-calendar type="text" m-cal-date="config" />

模板

<div class="miniCalendar"><label ng-click="selectDate()"><input type="text" ng-model="currentDate" disabled></label><div ng-show="selecting"><div><a><span ng-click="prev()">Prev</span></a><a><span ng-click="next()">Next</span></a><div ><span ng-bind="currentMonth">January</span>&nbsp;<span ng-bind="currentYear"></span></div></div><table><thead><tr><th ng-repeat="day in days"><span ng-bind="day.day"></span></th></tr></thead><tbody><tr ng-repeat="week in weeks"><td ng-repeat="d in week.days"><a ng-bind="d.day" ng-click="selectDay(d)">1</a></td></tr></tbody></table></div></div>

1 个答案:

答案 0 :(得分:0)

使用$ timeout而不是$ apply可以解决$ digest问题。

scope.updateDate = function(date) {
  $timeout(function() {
    scope.mCalDate = date;
    $parse(attrs.mCalDate).assign(scope.$parent, 'config');
  });
};