중첩 된 ng-click 호출 간의 이벤트 전파를 취소하는 가장 좋은 방법은 무엇입니까?


180

다음은 예입니다. 많은 사이트처럼 이미지 오버레이를 원한다고 가정 해 봅시다. 따라서 축소판을 클릭하면 전체 창 위에 검은 색 오버레이가 나타나고 더 큰 버전의 이미지가 가운데에 표시됩니다. 검은 색 오버레이를 클릭하면 사라집니다. 이미지를 클릭하면 다음 이미지를 보여주는 함수를 호출합니다.

HTML :

<div ng-controller="OverlayCtrl" class="overlay" ng-click="hideOverlay()">
    <img src="http://some_src" ng-click="nextImage()"/>
</div>

자바 스크립트 :

function OverlayCtrl($scope) {
    $scope.hideOverlay = function() {
        // Some code to hdie the overlay
    }
    $scope.nextImage = function() {
        // Some code to find and display the next image
    }
}

이미지를 클릭, 두 경우 문제는,이 설정에 그입니다 nextImage()hideOverlay()이라고합니다. 그러나 내가 원하는 것은 단지 nextImage()부르는 것입니다.

다음과 nextImage()같이 함수 에서 이벤트를 캡처하고 취소 할 수 있다는 것을 알고 있습니다 .

if (window.event) {
    window.event.stopPropagation();
}

...하지만이 스 니펫으로 오버레이 내부 요소의 모든 함수 앞에 접두사를 추가하지 않아도되는 AngularJS 방법이 더 나은지 알고 싶습니다.


1
return false기능 종료시
Jonathan de M.

1
나는이 그것을 할 수있는 방법 생각 onclick하지 ng-click.
Michael Scheper

답변:


193

@JosephSilber가 말한 것 또는 $ event 객체를 ng-click콜백에 전달하고 그 내부의 전파를 중지하십시오.

<div ng-controller="OverlayCtrl" class="overlay" ng-click="hideOverlay()">
  <img src="http://some_src" ng-click="nextImage($event)"/>
</div>
$scope.nextImage = function($event) {
  $event.stopPropagation();
  // Some code to find and display the next image
}

8
$ event.preventDefault ()를 사용하십시오. v> 1.5에서
KoolKabin

3
@KoolKabin Angular 1.5.8 및 $ event.stopPropagation ()을 여전히 사용하고 있습니다. 그러나 $ event.preventDefault ()는 작동하지 않습니다
HammerNL

1
나는 반대 상황이 있기 때문에 이상하다. stopPropagation은 더 이상 작동하지 않지만 preventDefault ()는 작동합니다. 차이점은 ng-click에서 직접 전화했다는 것입니다. <tr ng-click = "ctr.foo (); $ event.preventDefault ()"> ..... </ tr>
MilitelloVinx

171

사용 $event.stopPropagation():

<div ng-controller="OverlayCtrl" class="overlay" ng-click="hideOverlay()">
    <img src="http://some_src" ng-click="nextImage(); $event.stopPropagation()" />
</div>

데모는 다음과 같습니다. http://plnkr.co/edit/3Pp3NFbGxy30srl8OBmQ?p=preview


나는 ReferenceError: $event is not defined콘솔에 들어간다.
cilphex

예, 그렇습니다 ... 처음부터 별도의 간단한 버전을 작성할 때도 작동합니다. 개발 코드에서 무엇이 작동하지 않을 수 있는지 알아 내려고 노력 중입니다.
Dunno

@cilphex-최신 버전의 Angular를 사용하고 있습니까?
Joseph Silber

예-방금 문제를 발견했습니다. 테스트 할 때 $event.stopPropagation()작동하지 않는 곳에 두려고 했습니다. 제거하는 것을 잊었습니다. 그래서 내가 그것을 일한 곳에 두었을 때에도 그것이 두 번째로 불려지지 않았습니다. 고장난 복제품을 제거했으며 성공했습니다. 당신의 도움을 주셔서 감사합니다.
cilphex

101

나는 이것을 위해 지시문을 사용하는 아이디어를 좋아합니다.

.directive('stopEvent', function () {
    return {
        restrict: 'A',
        link: function (scope, element, attr) {
            element.bind('click', function (e) {
                e.stopPropagation();
            });
        }
    };
 });

그런 다음 지시문을 사용하십시오.

<div ng-controller="OverlayCtrl" class="overlay" ng-click="hideOverlay()">
    <img src="http://some_src" ng-click="nextImage()" stop-event/>
</div>

원하는 경우 https://stackoverflow.com/a/14547223/347216 과 같은 다른 질문에 대한 답변과 같이이 솔루션을보다 일반적으로 만들 수 있습니다.


2
요소가 DOM에서 동적으로 추가 / 제거 된 경우 요소를 '$ destroy'이벤트를 감시하여 핸들러를 바인드 해제 할 수 있습니다. 예를 들어 element.on ( '$ destroy', function () {/ * 여기서 바인딩 해제를 수행 * /});
broc.seib

이다 stop-event는 HTML 속성은? Mozilla 개발자 네트워크 또는 다른 곳에서는 찾을 수 없습니다.
Ehtesh Choudhury

3
@EhteshChoudhury- "stop-event"는 위의 JS 스 니펫에서 만든 새로운 지시문입니다. 더 선언하고 여기에 지침을 사용하는 방법에 대한 체크 아웃 : docs.angularjs.org/guide/directive
데이비드는 Ipsen에게

좋은 해결책! 실제로 angular-eat-eventbower에 지시문을 등록 했는데 비슷한 방식으로 작동합니다!
gion_13

작동하지 않는 것 같습니다. ng-click은 지시문 전에 평가합니다. 지시어가 실행되는 것을 막을 수는 있지만 다른 방법은 아닙니다.
Rafael

31

때로는 이렇게하는 것이 가장 합리적 일 수 있습니다.

<widget ng-click="myClickHandler(); $event.stopPropagation()"/>

나는 myClickHandler()다른 많은 곳에서 이벤트 전파를 멈추고 싶지 않기 때문에 이런 식으로 선택했다 .

물론, 핸들러 함수에 부울 매개 변수를 추가 할 수 있었지만 stopPropagation()just보다 훨씬 의미가 있습니다 true.


2
저는 항상이 버전을 좋아했습니다. 요소의 중첩은 내가 호출하는 기능과 관련이 없어야합니다.
mcfedr

$event.stopPropagation()내부 요소 에 추가 해야했습니다.
키쇼 파와 르

@KishorPawar : 왜? 대답에서 내가 한 방식이 효과가 없었습니까? 그렇지 않은 경우 Angular 작동 방식의 변경 또는 코드 문제로 인한 것인지 확인하는 것이 좋습니다.
Michael Scheper 2012

@MichaelScheper 나는 요소에 checkbox싸여있다 div. 내 div열이 12 열이고 checkbox3 열이 있습니다. 나는 함수를 호출하고 싶었 A의 클릭에 div와 기능 B의 클릭에 checkbox. 그래서 클릭했을 때 checkbox두 기능이 모두 호출되었습니다. 내가 추가하는 경우 ng-click="$event.stopPropagation()"checkbox, 나는 단지 기능이있어 B호출됩니다.
키쇼 파와 르

@KishorPawar : 아. 예, 나는 이것을 기대할 것입니다. 실제로 요점은 stopPropagation()이벤트가 부모 요소로 전파되는 것을 막는 것입니다. 에 B명시되어 있지 않기 때문에 어떻게 전화하는지 확실 하지 ng-click않지만 대답의 요점은 다음과 같이 할 수 있다는 것 <checkbox ng-click="B(); $event.stopPropagation()">입니다. 에 stopPropagation()기능 을 포함시킬 필요는 없습니다 B.
Michael Scheper 2012

7

이것은 나를 위해 작동합니다 :

<a href="" ng-click="doSomething($event)">Action</a>

this.doSomething = function($event) {
  $event.stopPropagation();
  $event.preventDefault();
};

Ctrl 키를 누르거나 누르지 않고 마우스 클릭을 처리하고 싶었습니다. 사용자가 Ctrl 키를 누른 상태에서 다양한 항목을 클릭 할 때 브라우저에서 HTML 요소 (내 경우에는 IE 11)의 선택 (및 강조 표시)을 중지하려면 ng-mousedown 이벤트를 사용하고 $ event를 통해 기본 동작을 취소해야했습니다. .preventDefault ()
pholpar

4

모든 링크에 전파 중지를 추가하지 않으려는 경우에도 작동합니다. 좀 더 확장 가능합니다.

$scope.hideOverlay( $event ){

   // only hide the overlay if we click on the actual div
   if( $event.target.className.indexOf('overlay') ) 
      // hide overlay logic

}

2
이 솔루션은 제공된 예제 (훌륭합니다!)에서 작동하지만 href / ng-click 이전에 외부 div에 n 개 이상의 중첩 요소가 있으면 작동하지 않습니다. 그런 다음 hideOverlay () 콜백이 호출되면 대상은 중첩 요소 중 하나이며 ng-click 지시문이있는 가장 바깥 쪽 요소가 아닙니다. 중첩 요소를 처리하기 위해 jquery를 사용하여 부모를 얻고 첫 번째 클릭 가능 (ng, click 등) 부모에 오버레이 클래스가 있는지 확인할 수 있지만 약간 번거 롭습니다 ...
Amir

console.log ( "potatooverlay".indexOf ( "overlay")! = -1); console.log (/ \ boverlay \ b / g.test ( "potatooverlay"));

각도는 당신을 할 것입니다 event.target.classList.indexOf('overlay') 그리고 그 트릭은 다른 div에 중첩되어있는 경우에도 잘 작동합니다
deltree

0

템플릿의 부모 요소에 ng-click = "$ event.stopPropagation"을 삽입하면 stopPropogation이 트리를 버블 링 할 때 포착되므로 전체 템플릿에 대해 한 번만 작성하면됩니다.


0

이벤트 전파 ng-click의 기본 동작을 수정 ng-click하고 중지하는 다른 지시문을 등록 할 수 있습니다 . 이런 식 $event.stopPropagation으로 손 으로 추가 할 필요가 없습니다 .

app.directive('ngClick', function() {
    return {
        restrict: 'A',
        compile: function($element, attr) {
            return function(scope, element, attr) {
                element.on('click', function(event) {
                    event.stopPropagation();
                });
            };
        }
    }
});

0
<div ng-click="methodName(event)"></div>

IN 컨트롤러 사용

$scope.methodName = function(event) { 
    event.stopPropagation();
}

첫 번째 방법으로 이벤트 보내기
Dinesh Jain

귀하의 답변은 4 년 전에 접수 된 것 중 아무 것도 추가하지 않습니다
Ilya Luzyanin
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.