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>