0

Ich habe eine QuickInfo-Anweisung, die auf Klick öffnen und schließen sollte und zusätzlich bei beliebigem Klick schließen. Da angular-translate nicht erlaubt, den Inhalt des Elements selbst zu ändern, füge ich stattdessen die Elemente der Richtlinie an.Vermeiden Sie Self-Toggle durch Ereignispropagation in der Direktive

Die Richtlinie sieht etwas wie folgt aus (bitte beachten Sie, dass dies eine vereinfachte Version ist):

{ 
    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; 
      } 
     }); 
    } 
} 

Das Problem dabei ist, dass das Click-Ereignis auf dem Element ausgelöst wird (scope.active = true) und dann propagiert Dokument, während es sofort geschlossen ist.

Wenn ich Propagation stoppe, funktioniert es in den meisten Fällen gut, der eine Fall ist nicht, wenn ich mehrere Instanzen der Direktive auf meiner Seite habe und nacheinander klicke (der erste öffnete sich und der andere sollte man öffnen, aber aufgrund der Ausbreitung ist gestoppt die document.click Falle der anderen Instanz nicht ausgelöst

Edit:.This fiddle demonstriert das Problem wenn Sie das grüne Feld darauf klicken und klicken Sie erneut auf es funktioniert, wenn. Sie klicken auf das grüne Kästchen und dann auf den Hintergrund, wenn Sie auf das grüne Kästchen und dann auf das andere grüne Kästchen klicken, aber beide sind geöffnet, obwohl das erste geschlossen werden sollte.
Wenn Sie die event.stopPropagation() auf line 20 entfernen, wird der Hinweis überhaupt nicht angezeigt, da der Klick auf das Feld zuerst ausgelöst wird, der Hinweis wird jedoch angezeigt, aber nach weiterer Ereignisausbreitung wird auch der Klick auf Hintergrund ausgelöst und sofort wieder geschlossen.


Wenn es eine insgesamt bessere ist Lösung für mein Problem zu schätzen wissen würde ich das auch

+0

Können Sie ein Beispiel jsfiddle, mit denen das Problem zu reproduzieren? –

+0

Sicher, überprüfen Sie die aktualisierte Frage – Aides

Antwort

0

Dies ist eine der Lösungen, die Ihnen helfen.

Live Beispiel auf 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>