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 событие другого экземпляра не срабатывают

Edit:.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>