AngularJS指令:模糊后不会触发ng-click

Mis*_*hko 11 angularjs angularjs-directive

DEMO

请考虑以下示例:

<input type="text" ng-model="client.phoneNumber" phone-number>
<button ng-click="doSomething()">Do Something</button>
Run Code Online (Sandbox Code Playgroud)
.directive("phoneNumber", function($compile) {
  return {
    restrict: 'A',
    scope: true,
    link: function(scope, element, attrs) { 
      scope.mobileNumberIsValid = true;

      var errorTemplate = "<span ng-show='!mobileNumberIsValid'>Error</span>";

      element.after($compile(errorTemplate)(scope)).on('blur', function() {
        scope.$apply(function() { 
          scope.mobileNumberIsValid = /^\d*$/.test(element.val());
        });
      });
    }  
  };
});
Run Code Online (Sandbox Code Playgroud)

看一下演示,如果你在电话号码的末尾添加说'a',然后点击按钮,doSomething()就不会被调用.如果再次单击该按钮,则会doSomething()调用该按钮.

为什么doSomething()第一次没有召唤?任何想法如何解决这一问题?

注意:保持模糊验证非常重要.

Dai*_*wei 9

说明

  1. 使用单击按钮,mousedown在按钮元素上触发事件.
  2. 输入已打开blur,模糊回调触发以验证输入值.
  3. 如果无效,则显示错误范围,按下按钮标记,从而光标左按钮区域.如果用户释放鼠标,mouseup则不会触发事件.这就像点击一个按钮但移动到它之外,然后释放鼠标以取消按钮点击.这是ng-click没有触发的原因.因为mouseup按钮上没有触发事件.

使用ng-pattern动态验证输入值,并且显示/隐藏错误跨度立即根据ngModel.$invalid属性.

演示1 http://jsbin.com/epEBECAy/14/edit

-----更新1 -----

根据作者的要求,用另一种解决方案更新了答案.

演示2 http://jsbin.com/epEBECAy/21/edit?html,js

HTML

<body ng-app="Demo" ng-controller="DemoCtrl as demoCtrl">
  <pre>{{ client | json }}</pre>
  <div id="wrapper">
    <input type="text" phone-number
           ng-model="client.phoneNumber"
           ng-blur="demoCtrl.validateInput(client.phoneNumber)">
  </div>
  <button ng-mousedown="demoCtrl.pauseValidation()" 
          ng-mouseup="demoCtrl.resumeValidation()" 
          ng-click="doSomething()">Do Something</button>
</body>
Run Code Online (Sandbox Code Playgroud)

逻辑

ng-blur在输入上使用了指令来触发验证.如果ng-mousedown之前被触发ng-blur,则ng-blur回调将被推迟直到ng-mouseup被触发.这是通过利用$q服务来实现的.


Tre*_*vor 4

这里: http: //jsbin.com/epEBECAy/25/edit

正如其他答案所解释的,在按钮上发生 onmouseup 事件之前,按钮会被跨度的外观移动,从而导致您遇到的问题。实现您想要的最简单的方法是以跨度的外观不会导致按钮移动的方式设置表单样式(从用户体验的角度来看,这通常是一个好主意)。您可以通过将input元素包装在div样式为 的中来完成此操作white-space:nowrap。只要跨度有足够的水平空间,按钮就不会移动,并且 ng-click 事件将按预期工作。

<div id="wrapper">
    <div style='white-space:nowrap;'>
        <input type="text" ng-model="client.phoneNumber" phone-number>
    </div>
    <button ng-click="doSomething()">Do Something</button>
</div>
Run Code Online (Sandbox Code Playgroud)