Search code examples
javascriptangularjsangularjs-digesttwo-way

Two way bindings trigger 10 digest() iteration reached


I have some problems with angular binding and I'm not very experienced with it. I will post all questions here as they are related. Here is some angularjs code snipped that triggers 10 digest() cycle reached. I found some similar posts and the cause is that a change is performed recursively in digest(), but I cannot find the cause in my example. Here is code:

<work-timekeepings-day timekeepings="dailyTimekeepingCtrl.timekeepingList  | timekeepingDay : dailyTimekeepingCtrl.selectedDay" day="dailyTimekeepingCtrl.selectedDay"></work-timekeepings-day>

Component:

var workTimekeepingsDay = TimekeepingsApp.component('workTimekeepingsDay', {
        templateUrl : 'angular/components/work-timekeepings-day.html',
        controllerAs: '$workTkDayCtrl',
        bindings : {
            timekeepings : '=',
            day: '='
        }
});

HTML template:

<div class="row lightgreen-row padding-5 border-rounded" ng-repeat-start="workTk in $workTkDayCtrl.timekeepings">
<div class="col-md-4"> <b> {{ workTk.user.firstName + ' ' + workTk.user.lastName }} </b> </div> </div> ...

Filter function:

var timekeepingDayFilter = TimekeepingsApp.filter('timekeepingDay', function() {
  return function(timekeepings, filterDay) {
      var result=[];
      angular.forEach(timekeepings, function(timekeeping) {
          var timekeepingDay = moment(timekeeping.workDay);
          if (timekeepingDay.isSame(filterDay, 'day')) {
             result.push(timekeeping);   
          }
        });
      return result;
  }

});

If I apply filter function inside HTML template it doesn't trigger the error, but the two-way binding with 'day' variable seems to not work properly. If I update 'dailyTimekeepingCtrl.selectedDay' in another component, bound in the same way, the change is not reflected in workTimekeepingsDay component. Here is the filter applied in component template:

<work-timekeepings-day timekeepings="dailyTimekeepingCtrl.timekeepingList" day="dailyTimekeepingCtrl.selectedDay"></work-timekeepings-day>



<div class="row lightgreen-row padding-5 border-rounded" ng-repeat-start="workTk in $workTkDayCtrl.timekeepings | timekeepingDay : day">
<div class="col-md-4"> <b> {{ workTk.user.firstName + ' ' + workTk.user.lastName }} </b> </div> </div> ..

Q1: Why is the 'digest() aborted' error occur if I am not updating the base array? How can I pass directly the filtered array to component in timekeepings variable?

Q2: Why is day variable not updated in component if dailyTimekeepingCtrl.selectedDay is updated?


Solution

  • I solved this by using lodash memoize function to use result from cash. Although I'd have preferred to not use an external library, but to change the algorithm, I am still happy with this.