Angularjs SMS verification code and second countdown

  Working H5 development requires SMS verification code and second countdown. It seems to be easier to do it with pure JS, but there are still some pitfalls to do with angularJS. I hereby record that there are several implementation methods as follows.

One.setTimeout way to achieve

<html>
<head>
	<title>AngularJs countdown</title>
</head>
<body>
	<div ng-controller="registerCtrl">
		<div>
			<div>
				<label>Captcha:</label>
				<input ng-model='verifCode' ng-disabled="verifCodeDisabled" placeholder="Please enter the verification code"></input>
				<button ng-bind="timing" ng-click="reacQuire()"></button>
			</div>
		</div>
		
		<div class="btn-group">
			<button ng-click="submitBtn()" ng-disabled="submitBtnDisabled">提交</button>
		</div>
	</div>
	<script src="jquery-1.8.3.js"></script>
	<script src="angular1.2.9.js"></script>
	<script src="index.js"></script>
</body>
</html>

index.js

var app = angular.module('myModule', []);

app.controller('registerCtrl', function($scope,$interval){
   	let countDown = 10;
	$scope.timing = countDown + "s";
	
	$scope.verifCode = '';
	$scope.verifCodeDisabled = false;
	$scope.submitBtnDisabled = false;
	
	function settime() {
		if(countDown > 0) {
			setTimeout(function() {settime(countDown--); $scope.$apply();}, 1000);
			$scope.timing = countDown + 's';
		}else {
			$scope.timing = "Reacquisition";
			$scope.verifCodeDisabled = true;
			$scope.submitBtnDisabled = true;
		}
	}
	
	settime();
	
	$scope.reacQuire = function() {
		if(countDown <= 0) {
			countDown = 10;
			$scope.timing = countDown + "s";
			settime();
            $scope.verifCodeDisabled = false;
			$scope.submitBtnDisabled = false;
		}
	};
	
	$scope.submitBtn = function() {
		if(!$scope.verifCode) {
			alert('Please enter the verification code');
			return;
		}
		alert('Submission successful');
	};
});

angular.element(document).ready(function() {   
	angular.bootstrap(document,['myModule']);  
});

running result:


  When the countdown reaches 0, the input box and the "Submit" button are grayed out, and the countdown button becomes "Refetch", as shown below:


  The implementation here is that you must pay attention to the $scope.$apply() in the settime function; here, if there is no $scope.$apply(); the countdown will only count down once, although JS does count down every second However, due to the existence of asynchrony (delay), when the callback function is executed, the dirty value detection in angularJS' own controller has ended, and the data change caused by the callback function cannot be detected, resulting in the page unable to count down normally. Similarly, if you add $scope.$apply(); at the settime function level, the effect is indeed OK, but F12 can see the angularJS error $apply already in progress. See: Understanding and Solving the AngularJS Error $apply already in progress .

 

2. Modifying the implementation of online viewing can also achieve the purpose

<html>
<head>
	<title>AngularJs countdown</title>
</head>
<body>
	<div ng-controller="registerCtrl">
		<a href="javascript:" ng-click="sendphonecode(reg_phone)" ng-class="paraclass" ng-bind="paracont">获取验证码</a>  
	</div>
	<script src="jquery-1.8.3.js"></script>
	<script src="angular1.2.9.js"></script>
	<script src="app.js"></script>
</body>
</html>

app.js

var app = angular.module('myModule', []);

app.controller('registerCtrl', function($scope, $interval) {
	
    $scope.paracont = "Get verification code";  
    $scope.paraclass = "but_null";  
    $scope.paraevent = true;
   
    var second = 10, timePromise = undefined;  
   
    function interval(){  
	  if(second<=0){  
		$interval.cancel(timePromise);  
		timePromise = undefined;  
		
		$scope.paracont = "Resend verification code";  
		$scope.paraclass = "but_null";  
		$scope.paraevent = true;  
	  }else{  
		$scope.paracont = second + "Resend in seconds";  
		$scope.paraclass = "not but_null";  
		second--;
	  }  
    }
	
	timePromise = $interval(interval, 1000, 100); //Indicates that it is executed once every second and executed 100 times
    
	$scope.sendphonecode = function() {
		if(second <= 0) {
			second = 10;
			timePromise = $interval(interval, 1000, 100); //Indicates that it is executed once every second and executed 100 times
		}
	};
});

angular.element(document).ready(function() {   
	angular.bootstrap(document,['myModule']);  
});

running result:

 

3. Use $interval to achieve

<html>
<head>
	<title>AngularJs countdown</title>
</head>
<body>
	<div ng-controller="registerCtrl">
		<div>
			<div>
				<label>Captcha:</label>
				<input ng-model='verifCode' ng-disabled="verifCodeDisabled" placeholder="Please enter the verification code"></input>
				<button ng-bind="timing" ng-click="reacQuire()"></button>
			</div>
		</div>
		
		<div class="btn-group">
			<button ng-click="submitBtn()" ng-disabled="submitBtnDisabled">提交</button>
		</div>
	</div>
	<script src="jquery-1.8.3.js"></script>
	<script src="angular1.2.9.js"></script>
	<script src="index02.js"></script>
</body>
</html>

index02.js

var app = angular.module('myModule', []);

app.controller('registerCtrl', function($scope,$interval){
   	let countDown = 10;
	$scope.timing = countDown + "s";
	
	$scope.verifCode = '';
	$scope.verifCodeDisabled = false;
	$scope.submitBtnDisabled = false;
	
	var time = $ interval (interval, 1000);
	
	function interval() {
		countDown--;
		$scope.timing = countDown + "s";
		if(countDown <= 0) {
			$interval.cancel(time);
			$scope.timing = "Reacquisition";
			$scope.verifCodeDisabled = true;
			$scope.submitBtnDisabled = true;
		}
	}
	
	$scope.reacQuire = function() {
		if(countDown <= 0) {
			countDown = 10;
			$scope.timing = countDown + "s";
			time = $interval(interval, 1000);
			$scope.verifCodeDisabled = false;
			$scope.submitBtnDisabled = false;
		}
	};
	
	$scope.submitBtn = function() {
		if(!$scope.verifCode) {
			alert('Please enter the verification code');
			return;
		}
		alert('Submission successful');
	};
});

angular.element(document).ready(function() {   
	angular.bootstrap(document,['myModule']);  
});

The operation effect is the same as that of method one.

 

4. Instruction method

<html>
<head>
	<title>AngularJs countdown</title>
</head>
<body>
	<div ng-controller="registerCtrl">
		 <timer-button show-timer="initTime" timeout="timeoutValue">获取验证码</timer-button>
	</div>
	<script src="jquery-1.8.3.js"></script>
	<script src="angular1.2.9.js"></script>
	<script src="index03.js"></script>
</body>
</html>

index03.js

var app = angular.module('myModule', []);

app.controller('registerCtrl', function($scope, $interval){
   	$scope.initTime = false;
	$scope.timeoutValue = 10000;
});

app.directive('timerButton', function($timeout, $interval){
    return {
        restrict: 'AE',
        scope: {
            showTimer: '=',
            timeout: '='
        },
        link: function(scope, element, attrs){
            scope.timer = false;
            scope.timerCount = scope.timeout / 1000;
            scope.text = "获取验证码";

            scope.onClick = function(){
                scope.showTimer = true;
                scope.timer = true;
                scope.text = 's';
                var counter = $interval(function(){
					if(scope.timerCount > 0) {
						scope.timerCount = scope.timerCount - 1;
					}else {
						scope.timerCount = '';
					}
                }, 1000);

                $timeout(function(){
                    scope.text = "重新获取";
                    scope.timer = false;
                    $interval.cancel(counter);
                    scope.showTimer = false;
                    scope.timerCount = scope.timeout / 1000;
                }, scope.timeout);
            }
        },
        template: '<button ng-click="onClick()" class="button button-calm xgmm-btn" ng-disabled="timer"><span ng-show="showTimer">{{ timerCount }}</span>{{text}}</button>'
    };
});

angular.element(document).ready(function() {   
	angular.bootstrap(document,['myModule']);  
});

运行效果:

  刚打开页面,显示”获取验证码“按钮

  点击”获取验证码“按钮,进行秒倒计时

  倒计到0时,显示”重新获取“,此时,可点击“重新获取”按钮重新进行倒计时。

 

五.AngularJs $interval 和 $timeout

1.$interval

  window.setInterval的Angular包装形式。Fn是每次延迟时间后被执行的函数。

  间隔函数的返回值是一个承诺。这个承诺将在每个间隔刻度被通知,并且到达规定迭代次数后被取消,如果迭代次数未定义,则无限制的执行。通知的值将是运行的迭代次数。取消一个间隔,调用$intreval.cancel(promise)。

  备注:当你执行完这项服务后应该把它销毁。特别是当controller或者directive元素被销毁时而$interval未被销毁。你应该考虑到在适当的时候取消interval事件。

使用:$interval(fn,delay,[count],[invokeApply],[Pass]);

  fn:一个将被反复执行的函数。

  delay:每次调用的间隔毫秒数值。

  count:循环次数的数值,如果没设置,则无限制循环。

  invokeApply:如果设置为false,则避开脏值检查,否则将调用$apply。

  Pass:函数的附加参数。

方法:cancel(promise);

  取消与承诺相关联的任务。

  promise:$interval函数的返回值。

使用代码:

(function () {
    angular.module("Demo", [])
    .controller("testCtrl",["$interval",testCtrl]);
    function testCtrl($interval){
      var toDo = function () {
          console.log("Hello World");
      };
      $interval(toDo, 3000, 10);
    };
  }());

2.$timeout

  window.setTimeout的Angular包装形式。Fn函数包装成一个try/catch块,代表$exceptionHandler服务里的任何异常。

  timeout函数的返回值是一个promise,当到达设置的超时时间时,这个承诺将被解决,并执行timeout函数。

  需要取消timeout,需要调用$timeout.cancel(promise);

使用: $timeout(fn,[delay],[invokeApply]);

  fn: A function that will be deferred.

  delay: delay time in milliseconds.

  invokeApply: If set to false, skip dirty value detection, otherwise $apply will be invoked.

Method: cancel(promise);

  Cancel the task associated with the promise. As a result of this, commitments will be resolved in an abandoned manner.

  promise: The promise returned by the $timeout function.

Use code:

(function () {
    angular.module("Demo", [])
    .controller("testCtrl",["$timeout",testCtrl]);
    function testCtrl($timeout){
      var toDo = function () {
          console.log("Hello World");
      };
      $timeout(toDo,5000)
    };
  }());

  The general usage method can be used in the same way as setInterval and setTimeout of native js, and some usage tips can be used in browser single-threaded event execution.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326477949&siteId=291194637