AngularJS指令在过滤后丢失变量值

时间:2015-04-15 07:59:21

标签: javascript angularjs angularjs-directive angularjs-scope

我有一个具有不同标题的秒表,当我开始观看它运行时,10秒后它会弹出警报。我可以在标题顶部过滤手表,当我重置过滤器时,正在运行的手表没有显示时间但它会在10秒钟后发出警报。为什么过滤后绑定不起作用?这里有什么问题?我该如何解决? 找到plunker here完整代码,HTML就在plunker中。

单击播放将启动手表,暂停将暂停并停止 - 停止观看。

< script type = "text/javascript" > angular.module('App', [])
        .controller('MainCtrl', function ($scope, $interval) {
        $interval(function () {
            $scope.sharedTime = new Date();
        }, 500);
    })
        .directive('stopwatch', function () {
        return {
            restrict: 'AE',
            templateUrl: 'stopwatch.html',
            scope: {
                // Set title in the isolate scope from the title attribute on the     directive's element.
                title: '@title',
                // Set up a bi-directional binding between currentTime on the local scope and the parent
                // scope's variable containing the current time that's the value of the time attribute.
                currentTime: '=time'
            },
            link: function (scope, element, attrs, ctrl) {},
            controllerAs: 'swctrl',
            controller: function ($scope, $interval) {
                var self = this;
                var time = 0;
                var mode = 1;
                var status = 0;
                var timer_id;
                self.play = 1;
                self.start = function (interval) {
                    self.play = 0;
                    var timeRet;
                    interval = 1000;
                    if (status == 0) {
                        status = 1;

                        function timeRun() {
                            if (time < 86400) {
                                time++;
                                timeRet = self.getElapsedMs();
                                if (time == 10) {
                                    alert("Its 10 seconds")
                                }

                                if (typeof (callback) === 'function') callback(timeRet);
                            }
                        };
                        return timer_id = setInterval(timeRun, interval);
                    }

                };

                self.pause = function () {
                    self.play = 1;
                    if (status == 1) {
                        status = 0;
                        clearInterval(timer_id);
                    }
                };

                self.stop = function () {
                    self.play = 1;
                    sec = (typeof (sec) !== 'undefined') ? sec : 0;
                    time = sec;
                    if (status == 1) {
                        status = 0;
                        clearInterval(timer_id);
                    }


                };

                self.getTime = function () {
                    return time;
                };



                self.getElapsedMs = function () {

                    var second = time % 60;
                    var minute = Math.floor(time / 60) % 60;
                    var hour = Math.floor(time / 3600) % 60;

                    second = (second < 10) ? '0' + second : second;
                    minute = (minute < 10) ? '0' + minute : minute;
                    hour = (hour < 10) ? '0' + hour : hour;

                    var timeObj = hour + ":" + minute + ":" + second

                    return timeObj;
                };
            }
        }
    }); < /script>

如何重现:激活一个,然后输入&#34;两个&#34;在文本框中,然后擦除它。您将看到一个计时器显示00:00:00

2 个答案:

答案 0 :(得分:0)

ng-repeat中过滤在数组上应用过滤关键字并返回一个新子集,从而销毁先前创建的指令。

来自docs

  

从数组中选择项目的子集并将其作为新数组返回。

如果你放在链接功能内:

scope.$on("$destroy", function () {
    console.log("destroying");
});

您会看到它会记录因过滤而消除的每个秒表。

因此,我只是隐藏秒表的整个div而不是使用过滤器:

<div  ng-show="!filter || title.indexOf(filter) > -1">
    <div class="timer" >{{title}}<br>
       {{swctrl.getElapsedMs() | limitTo:6}}<span class="sec">
       {{swctrl.getElapsedMs() | limitTo:-2}}</span>

   </div>
  <a href="" ng-show ="swctrl.play" id="timerPlay" class="play" ng-click="swctrl.start();"> Play</a>
  <a href=""  ng-show ="!swctrl.play" id="timerPause" class="pause"  ng-click="swctrl.pause();">Pause</a>
  <a href=""  id="timerStop" class="stop" ng-click="swctrl.stop();" >Stop</a>    
</div>

您的用法变为:

<div ng-repeat="item in arr">
     <div stopwatch title="{{item}}" filter="filters" time="sharedTime">
</div>

Plunker

答案 1 :(得分:0)

Omri Aharon解释了问题所在。我个人将秒表功能移到工厂,并将其实例传递给你的指令。

.factory('StopWatch', function() {
    function StopWatch(name) {
      this.name = name;
      this.time = 0;
      this.mode = 1;
      this.status = 0;
      this.play = 1;
    }

    StopWatch.prototype.start = function(interval) {

      var self = this;
      self.play = 0;

      var timeRet;


      interval = 1000;  
      if(self.status == 0)
      {
        self.status = 1;
        function timeRun()
        {       
            if(self.time < 86400)
            {
              self.time++;
              timeRet =  self.getElapsedMs();
              if(self.time == 10)
              {
                alert("Its 10 seconds")
              }

              if(typeof(callback) === 'function') callback(timeRet);
            }               
        };
        return self.timer_id = setInterval(timeRun, interval);     
      }

    };

    StopWatch.prototype.pause = function() {
      this.play = 1;
      if(this.status == 1)
      {
        this.status = 0;
        clearInterval(this.timer_id);
      }
    };

    StopWatch.prototype.stop = function() {
      this.play = 1;
      var sec = (typeof(sec) !== 'undefined') ? sec : 0;
      this.time = sec;
      if(this.status == 1)
      {
        this.status = 0;
        clearInterval(this.timer_id);
      }
    };

    StopWatch.prototype.getTime = function() {
      return this.time;
    };

    StopWatch.prototype.getElapsedMs = function() {

      var second = this.time % 60;
      var minute = Math.floor(this.time / 60) % 60;
      var hour = Math.floor(this.time / 3600) % 60;

      second = (second < 10) ? '0'+second : second;
      minute = (minute < 10) ? '0'+minute : minute;
      hour = (hour < 10) ? '0'+hour : hour;

      var timeObj = hour+":"+minute+":"+second

      return timeObj;

    };

    return StopWatch;
})

所以你要创建秒表:

$scope.timers = [
  new StopWatch('one'),
  new StopWatch('two'),
  new StopWatch('three'),
  new StopWatch('four')
];

然后重复并传入指令:

<div ng-repeat="item in timers | filter:filter_">
  {{item.name}}
  <div stopwatch="item"></div>
</div>

Plunker