0

我有一个工具提示指令,它应该在点击时打开/关闭并在任意点击时关闭。由于angular-translate不允许改变元素本身的内容,我反而附加指令的元素。避免通过指令中的事件传播自行切换

该指令看起来有点像这样(请注意,这是一个简化版本):

{ 
    restrict: 'A', 
    scope: {}, 
    compile: function(element) 
    { 
     element.after('<div class="toggle"></div> 
      <div class="message" ng-show="active"></div>'); 
    }, 
    link: function(scope, element) 
    { 
     angular.element(element.siblings('toggle')).click(function() 
     { 
      scope.$apply(function() 
      { 
       scope.active = !scope.active; 
      } 
     }); 
     angular.element(document).click(function() 
     { 
      scope.$apply(function() 
      { 
       scope.active = false; 
      } 
     }); 
    } 
} 

但问题是,在元素上的点击事件被触发(scope.active = true),然后传播到文件,而它立即关闭。

但是,如果我停止传播,它在大多数情况下都可以正常工作,但它并不是在我的页面上有多个指令实例并单击一个接一个地点击时(第一个应该关闭,另外一个应该打开,但由于传播停止其他实例的document.click不会触发事件

编辑:This fiddle演示了此问题。如果你点击绿色的盒子,然后再次单击它,它的工作原理,如果。您点击绿色框,然后点击它的工作背景,如果您点击绿色框,然后另一个绿色框打开,但第一个应该关闭。
如果您删除event.stopPropagation()line 20该提示根本不会显示,因为点击该框时首先会触发该提示,但在进一步事件传播后,点击背景也会触发,并立即关闭该提示。


如果有我的问题的整体更好的解决方案我很感激以及

+0

你能举一个例子的jsfiddle与重现该问题? –

+0

当然,检查更新的问题 – Aides

回答

0

这是解决方案,这将有助于你的一个。

jsfiddle上的现场示例。

angular.module('app', []) 
 
    .controller('testCtrl', ['$scope', 
 
    function($scope) { 
 
     var self = this; 
 
    } 
 
    ]) 
 
    .directive('hintDirective', ['$compile', 
 
    function($compile) { 
 
     var directiveHint = []; 
 
     return { 
 
     restrict: 'A', 
 
     transclude: true, 
 
     scope: {}, 
 
     template: '<ng-transclude></ng-transclude><span ng-click="toggle($event)" class="toggle"></span><div class="message" ng-show="active">Hint Message</div>', 
 
     link: function(scope, element) { 
 
      scope.active = false; 
 
      directiveHint.push(scope); 
 
      var span = element.find('span')[1]; 
 
      scope.toggle = function($ev) { 
 
      scope.active = !scope.active; 
 
      closeOther(scope); 
 
      $ev.stopPropagation(); 
 
      } 
 

 
      function closeOther(scope) { 
 
      angular.forEach(directiveHint, function(sc) { 
 
       if (sc != scope) { 
 
       closeActive(sc) 
 
       } 
 
      }); 
 
      } 
 

 
      function closeAll() { 
 
      angular.forEach(directiveHint, function(sc) { 
 
       closeActive(sc) 
 
      }); 
 
      } 
 

 
      function closeActive(sc) { 
 
      if (sc.active) 
 
       sc.active = false; 
 
      } 
 

 
      function documentClick(event) { 
 
      scope.$apply(function() { 
 
       closeAll(); 
 
      }); 
 
      } 
 
      var $body = angular.element(document.body); 
 
      if (!$body.hasClass('hint-directive-click')) { 
 
      angular.element(document).bind('click', documentClick); 
 
      $body.addClass('hint-directive-click'); 
 
      } 
 

 
      scope.$on('$destroy', function() { 
 
      angular.forEach(directiveHint, function(sc, i) { 
 
       if (sc == scope) 
 
       directiveHint.splice(i); 
 
      }); 
 
      }) 
 
     } 
 
     } 
 
    } 
 
    ]);
html, 
 
body { 
 
    width: 100%; 
 
    height: 100%; 
 
} 
 
.split { 
 
    float: left; 
 
    width: 50%; 
 
    height: 100%; 
 
} 
 
.toggle { 
 
    display: inline-block; 
 
    width: 1em; 
 
    height: 1em; 
 
    background-color: green; 
 
} 
 
p { 
 
    float: left; 
 
} 
 
.message { 
 
    background-color: grey; 
 
    width: 200px; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script> 
 
<div ng-app="app"> 
 
    <div class="split"> 
 
    <br> 
 
    <br> 
 
    <br> 
 
    <br> 
 
    <br> 
 
    <p hint-directive> 
 
     Text1 
 
    </p> 
 
    </div> 
 
    <div class="split"> 
 
    <br> 
 
    <br> 
 
    <br> 
 
    <br> 
 
    <br> 
 
    <p hint-directive> 
 
     Text2 
 
    </p> 
 
    <label> 
 
     <input type="checkbox" ng-model="text3Enable">Enable text3</label> 
 
    <p hint-directive ng-if="text3Enable"> 
 
     Text3 
 
    </p> 
 
    </div> 
 
</div>