2017-05-29 49 views
6

我正在使用日期選擇器在AngularUI上實現範圍選擇器。在自定義指令中使用ng-change和ng-model - 摘要循環

的HTML代碼來調用自定義的時間選擇:

<time-range 
     name-time="Hours" 
     max-length="2" min="00" max="23" step="01" 
     ng-model="hours" 
     ng-change="updateHours()"> 
    </time-range> 
<time-range 
     name-time="Minutes" 
     max-length="2" min="00" max="59" step="01" 
     ng-model="minutes" 
     ng-change="updateMinutes()"> 
    </time-range> 

這裏是我的指令:

模塊app.common.directives {

export interface ITimeRangeScope extends ng.IScope { 
     ngModel: string; 
     ngChange; 
     nameTime: string; 
     maxLength: number; 
     min: number; 
     max: number; 
     step: number; 
     vm: TimeRangeController; 
    } 

    export class TimeRange implements ng.IDirective { 
     scope: any = { 
      ngModel: "=", 
      ngChange: "=", 
      nameTime: "@", 
      maxLength: "@", 
      min: "@", 
      max: "@", 
      step: "@" 
     }; 
     controller = TimeRangeController; 

     template = ` 
      <div class="custom-range-slider"> 
       <span> {{nameTime}}: </span> 
       <div style="padding-bottom: 5px;"></div> 
       <input type="range" max-length="{{maxLength}}" min="{{min}}" max="{{max}}" step="{{step}}" ng-model="ngModel"ng-change="ngChange"> 
      </div> 
     `; 

     restrict: string = "E"; 

     //Use this to register this directive 
     static factory(): ng.IDirectiveFactory { 
      var directive: ng.IDirectiveFactory =() => new TimeRange(); 
      return directive; 
     } 
    } 

    class TimeRangeController { 
     init; 
     val; 

     // @ngInject 
     constructor(
      private $scope: ITimeRangeScope, 
      private $element: ng.IAugmentedJQuery, 
      private $attrs, 
      private $transclude 
     ) { 
      $scope.vm = this; 

      this.$scope.$watch("ngModel",() => { 
       this.showPercentage(); 
       this.drawRangeTrace(); 
      }); 
     } 

     showPercentage() { 
      this.init = parseInt(this.$scope.ngModel); 
      var min = parseInt(this.$element.attr('min')); 
      var max = parseInt(this.$element.attr('max')); 
      this.val = (this.init - min)/max - min; 
     } 

     drawRangeTrace() { 
      this.$element.children().find('input').css('background-image', 
       '-webkit-gradient(linear, left top, right top, ' 
       + 'color-stop(' + this.val + ', #2196F3), ' 
       + 'color-stop(' + this.val + ', #C5C5C5)' 
       + ')' 
      ); 
      this.$element.children().find('input').val(this.init); 
     } 
    } 
} 

這是它是如何工作的:

Date Picker with sliders

但我recived的一個錯誤:在您的異常10 $摘要()

> vendor.min.js:84275 Uncaught Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting! 
Watchers fired in the last 5 iterations: [[{"msg":"fn: ngModelWatch","newVal":"2017-05-28T22:00:00.000Z","oldVal":"2017-05-28T22:00:00.000Z"},{"msg":"fn: ngModelWatch","newVal":"2017-05-28T22:00:00.000Z","oldVal":"2017-05-28T22:00:00.000Z"},{"msg":"fn: ngModelWatch","newVal":"2017-05-28T22:00:00.000Z","oldVal":"2017-05-28T22:00:00.000Z"}],[{"msg":"fn: ngModelWatch","newVal":"2017-05-28T22:00:00.000Z","oldVal":"2017-05-28T22:00:00.000Z"},{"msg":"fn: ngModelWatch","newVal":"2017-05-28T22:00:00.000Z","oldVal":"2017-05-28T22:00:00.000Z"},{"msg":"fn: ngModelWatch","newVal":"2017-05-28T22:00:00.000Z","oldVal":"2017-05-28T22:00:00.000Z"}],[{"msg":"fn: ngModelWatch","newVal":"2017-05-28T22:00:00.000Z","oldVal":"2017-05-28T22:00:00.000Z"},{"msg":"fn: ngModelWatch","newVal":"2017-05-28T22:00:00.000Z","oldVal":"2017-05-28T22:00:00.000Z"},{"msg":"fn: ngModelWatch","newVal":"2017-05-28T22:00:00.000Z","oldVal":"2017-05-28T22:00:00.000Z"}],[{"msg":"fn: ngModelWatch","newVal":"2017-05-28T22:00:00.000Z","oldVal":"2017-05-28T22:00:00.000Z"},{"msg":"fn: ngModelWatch","newVal":"2017-05-28T22:00:00.000Z","oldVal":"2017-05-28T22:00:00.000Z"},{"msg":"fn: ngModelWatch","newVal":"2017-05-28T22:00:00.000Z","oldVal":"2017-05-28T22:00:00.000Z"}],[{"msg":"fn: ngModelWatch","newVal":"2017-05-28T22:00:00.000Z","oldVal":"2017-05-28T22:00:00.000Z"},{"msg":"fn: ngModelWatch","newVal":"2017-05-28T22:00:00.000Z","oldVal":"2017-05-28T22:00:00.000Z"},{"msg":"fn: ngModelWatch","newVal":"2017-05-28T22:00:00.000Z","oldVal":"2017-05-28T22:00:00.000Z"}]] 
http://errors.angularjs.org/1.6.1/$rootScope/infdig?p0=10&p1=%5B%5B%7B%22ms…%3A00.000Z%22%2C%22oldVal%22%3A%222017-05-28T22%3A00%3A00.000Z%22%7D%5D%5D 
    at vendor.min.js:84275 
    at Scope.$digest (vendor.min.js:102059) 
    at Scope.$apply (vendor.min.js:102287) 
    at vendor.min.js:104131 
    at completeOutstandingRequest (vendor.min.js:90318) 
    at vendor.min.js:90597 

回答

2

我改變ngChange到的onUpdate。

在HTML:

on-update="updateHours()" 

我在從ngCgange改變加入;在指令

onUpdate:() => any; 

綁定範圍:

onUpdate: "&",

阿爾稱爲方法添加

class TimeRangeController { 
     init; 
     val; 
     onUpdate; // Override callback for adding an entity to the list 

     // @ngInject 
     constructor(
      private $scope: ITimeRangeScope, 
      private $element: ng.IAugmentedJQuery, 
      private $attrs, 
      private $transclude 
     ) { 
      $scope.vm = this; 

      this.$scope.$watch("ngModel",() => { 
       this.showPercentage(); 
       this.drawRangeTrace(); 
       this.add(); 
      }); 
     } 

     add() { 
      if (this.$attrs.onUpdate != undefined) { 
        this.$scope.onUpdate(); 
       } 
     } 

     showPercentage() { 
      this.init = parseInt(this.$scope.ngModel); 
      var min = parseInt(this.$element.attr('min')); 
      var max = parseInt(this.$element.attr('max')); 
      this.val = (this.init - min)/max - min; 
     } 

     drawRangeTrace() { 
      this.$element.children().find('input').css('background-image', 
       '-webkit-gradient(linear, left top, right top, ' 
       + 'color-stop(' + this.val + ', #2196F3), ' 
       + 'color-stop(' + this.val + ', #C5C5C5)' 
       + ')' 
      ); 
      this.$element.children().find('input').val(this.init); 
     } 
    } 
1

搜索答案:

觀察者在最近的5次迭代中解僱了[[{ 「msg」:「fn: ngModelWatch」,「newVal」:「2017-05-28T22:00:00.000Z」,「oldVal」:「2017-05-28T22:00:00.000Z」} ...]]]

看起來像你這樣的問題:

this.$scope.$watch("ngModel",() => { 
      this.showPercentage(); 
      this.drawRangeTrace(); 
     }); 

你聽上this.$scope.ngModel出於某種原因,方法this.showPercentage()this.drawRangeTrace()更改ngModel將觸發額外的守望者。

爲避免內存泄漏,Angular會拋出此異常以擺脫無限摘要循環循環。


儘量簡化你的代碼,發現有問題的代碼片段由開始註釋行的方法this.showPercentage()線內容和this.drawRangeTrace()

+1

現在我刪除從指令還指令NG-變化的模板,我在ngModel watcher上添加了這個「hardcode」。$ scope。$ parent.updateMinutes(); this。$ scope。$ parent.updateHours(); – Andrej