チェックボックスとフィルターオプションを使用して複数選択ドロップダウンリストを作成しようとしています。外部をクリックしてリストを非表示にしようとしていますが、その方法がわかりませんでした。あなたの助けに感謝。
9 に答える
注意してください、ソリューション(質問で提供されたプランカー)は、2番目のポップアップ(複数選択のあるページ)を開くときに、他のボックスのポップアップを閉じません。
ボックスをクリックして新しいポップアップを開くと、クリック イベントは常に停止します。イベントは、開いている他のポップアップに到達することはありません (それらを閉じるため)。
event.stopPropagation();
行を削除し、ポップアップのすべての子要素を一致させることでこれを解決しました。
events 要素がポップアップのどの子要素とも一致しない場合にのみ、ポップアップは閉じられます。
ディレクティブ コードを次のように変更しました。
select.html (ディレクティブ コード)
link: function(scope, element, attr){
scope.isPopupVisible = false;
scope.toggleSelect = function(){
scope.isPopupVisible = !scope.isPopupVisible;
}
$(document).bind('click', function(event){
var isClickedElementChildOfPopup = element
.find(event.target)
.length > 0;
if (isClickedElementChildOfPopup)
return;
scope.$apply(function(){
scope.isPopupVisible = false;
});
});
}
私はあなたのプランカーをフォークし、変更を適用しました:
プランカー: 外側をクリックするとポップアップ div を非表示にする
スクリーンショット:
これは古い投稿ですが、これが誰かに役立つ場合は、角度以外に依存しない外側のクリックの実際の例です。
module('clickOutside', []).directive('clickOutside', function ($document) {
return {
restrict: 'A',
scope: {
clickOutside: '&'
},
link: function (scope, el, attr) {
$document.on('click', function (e) {
if (el !== e.target && !el[0].contains(e.target)) {
scope.$apply(function () {
scope.$eval(scope.clickOutside);
});
}
});
}
}
});
OK、イベントがAngular Worldの外で発生しているため、$ apply()を呼び出す必要がありました(ドキュメントに従って)。
element.bind('click', function(event) {
event.stopPropagation();
});
$document.bind('click', function(){
scope.isVisible = false;
scope.$apply();
});
次のようなグローバル クリック イベントをリッスンして実現しました。
.directive('globalEvents', ['News', function(News) {
// Used for global events
return function(scope, element) {
// Listens for a mouse click
// Need to close drop down menus
element.bind('click', function(e) {
News.setClick(e.target);
});
}
}])
その後、イベント自体がニュース サービスを介してブロードキャストされます。
angular.factory('News', ['$rootScope', function($rootScope) {
var news = {};
news.setClick = function( target ) {
this.clickTarget = target;
$rootScope.$broadcast('click');
};
}]);
その後、必要な場所でブロードキャストを聞くことができます。ディレクティブの例を次に示します。
.directive('dropdown', ['News', function(News) {
// Drop down menu für the logo button
return {
restrict: 'E',
scope: {},
link: function(scope, element) {
var opened = true;
// Toggles the visibility of the drop down menu
scope.toggle = function() {
element.removeClass(opened ? 'closed' : 'opened');
element.addClass(opened ? 'opened' : 'closed');
};
// Listens for the global click event broad-casted by the News service
scope.$on('click', function() {
if (element.find(News.clickTarget.tagName)[0] !== News.clickTarget) {
scope.toggle(false);
}
});
// Init
scope.toggle();
}
}
}])
それが役立つことを願っています!
というクールなディレクティブがありangular-click-outside
ます。プロジェクトで使用できます。使い方はとても簡単です:
提供された回答に完全に満足できなかったので、自分で作成しました。改良点:
- スコープのより防御的な更新。適用/ダイジェストがすでに進行中かどうかを確認します
- ユーザーがエスケープキーを押すと、divも閉じます
- div が閉じられると、ウィンドウ イベントのバインドが解除されます (リークを防ぎます)。
スコープが破棄されると、ウィンドウ イベントのバインドが解除されます (リークを防ぎます)。
function link(scope, $element, attributes, $window) {
var el = $element[0], $$window = angular.element($window); function onClick(event) { console.log('window clicked'); // might need to polyfill node.contains if (el.contains(event.target)) { console.log('click inside element'); return; } scope.isActive = !scope.isActive; if (!scope.$$phase) { scope.$apply(); } } function onKeyUp(event) { if (event.keyCode !== 27) { return; } console.log('escape pressed'); scope.isActive = false; if (!scope.$$phase) { scope.$apply(); } } function bindCloseHandler() { console.log('binding window click event'); $$window.on('click', onClick); $$window.on('keyup', onKeyUp); } function unbindCloseHandler() { console.log('unbinding window click event'); $$window.off('click', onClick); $$window.off('keyup', onKeyUp); } scope.$watch('isActive', function(newValue, oldValue) { if (newValue) { bindCloseHandler(); } else { unbindCloseHandler(); } }); // prevent leaks - destroy handlers when scope is destroyed scope.$on('$destroy', function() { unbindCloseHandler(); });
}
リンク機能に$window
直接入ります。ただし、取得するためにこれを正確に行う必要はありません$window
。
function directive($window) {
return {
restrict: 'AE',
link: function(scope, $element, attributes) {
link.call(null, scope, $element, attributes, $window);
}
};
}