AngularJS ng- 클릭 중지


433

테이블 행에 클릭 이벤트가 있으며이 행에는 클릭 이벤트가있는 삭제 버튼도 있습니다. 삭제 버튼을 클릭하면 행의 클릭 이벤트도 시작됩니다.

여기 내 코드가 있습니다.

<tbody>
  <tr ng-repeat="user in users" class="repeat-animation" ng-click="showUser(user, $index)">
    <td>{{user.firstname}}</td>
    <td>{{user.lastname}}</td>
    <td>{{user.email}}</td>
    <td><button class="btn red btn-sm" ng-click="deleteUser(user.id, $index)">Delete</button></td>
  </tr>
</tbody>

showUser표 셀에서 삭제 버튼을 클릭하면 이벤트가 발생 하지 않도록 하려면 어떻게해야합니까?

답변:


801

ngClick 지시문 (및 다른 모든 이벤트 지시문)은 $event동일한 범위에서 사용 가능한 변수를 만듭니다 . 이 변수는 JS event객체에 대한 참조 이며 stopPropagation()다음 을 호출하는 데 사용할 수 있습니다 .

<table>
  <tr ng-repeat="user in users" ng-click="showUser(user)">
    <td>{{user.firstname}}</td>
    <td>{{user.lastname}}</td>
    <td>
      <button class="btn" ng-click="deleteUser(user.id, $index); $event.stopPropagation();">
        Delete
      </button>
    </td>              
  </tr>
</table>

PLUNKER


2
이것이 컨트롤러 코드에서 사용 가능한지 알 수 없습니다-$ scope. $ event가 작동하지 않는 것 같습니다. 어떤 아이디어?
user1338062 2019

93
@event 객체는 ng-click 지시문 안에 만들어지며 ng-click핸들러 함수 에 전달할 수 ng-click="deleteUser(user.id, $event)"있습니다.
Stewie

6
고마워요, 일종의 생각하지만, 여전히 악취가 나는 것
같습니다

2
이런 식으로 여러 표현식을 실행하는 것은 반 패턴이라고 생각합니다. 왜 $ event를 deleteUser ()에 대한 세 번째 인수로 전달한 다음 해당 함수 내에서 stopPropagation ()을 중지하지 않습니까?
djheru

18
나도 추가해야 $event.preventDefault()했다. 그렇지 않으면 호출 $event.stopPropagation()하면 버튼을 클릭 할 때 응용 프로그램의 루트로 리디렉션됩니다.
Desty

124

Stewie의 답변에 추가. 콜백이 전파 중지 여부를 결정할 때 $event객체를 콜백에 전달하는 것이 유용하다는 것을 알았습니다 .

<div ng-click="parentHandler($event)">
  <div ng-click="childHandler($event)">
  </div>
</div>

그런 다음 콜백 자체에서 이벤트 전파를 중지해야하는지 여부를 결정할 수 있습니다.

$scope.childHandler = function ($event) {
  if (wanna_stop_it()) {
    $event.stopPropagation();
  }
  ...
};

10
이것은 html 속성에서 여러 표현식을 실행하는 것보다 더 우아합니다.
Eason

3
html ng-click 지시문에 '$ event'인수를 넣어야합니다. 나는 처음에 그것을 우연히 발견했다.
ThinkBonobo

1
즉각적인 중지를 위해서는 $ event.stopImmediatePropagation ()을 사용하십시오
Edgar Chavolla

매우 단순하지만 무시됩니다. 선택한 답변을보고 "정말?이 못생긴?" 그것을 매개 변수로 전달하는 것을 깨닫지 못했습니다. 정말 좋아요
tfrascaroli

10

클릭이 적용되는 영역을 제한 할 수있는 지시문을 작성했습니다. 이 시나리오는 이와 같은 특정 시나리오에 사용될 수 있으므로 사례별로 클릭을 처리하는 대신 "클릭이이 요소에서 나오지 않습니다"라고 말할 수 있습니다.

다음과 같이 사용하십시오.

<table>
  <tr ng-repeat="user in users" ng-click="showUser(user)">
    <td>{{user.firstname}}</td>
    <td>{{user.lastname}}</td>
    <td isolate-click>
      <button class="btn" ng-click="deleteUser(user.id, $index);">
        Delete
      </button>
    </td>              
  </tr>
</table>

이렇게하면 버튼뿐만 아니라 마지막 셀의 모든 클릭을 막을 수 있습니다. 그것이 원하는 것이 아니라면 다음과 같이 버튼을 감싸고 싶을 수도 있습니다.

<span isolate-click>
    <button class="btn" ng-click="deleteUser(user.id, $index);">
        Delete
    </button>
</span>

지시문 코드는 다음과 같습니다.

angular.module('awesome', []).directive('isolateClick', function() {
    return {
        link: function(scope, elem) {
            elem.on('click', function(e){
                e.stopPropagation();
            });
        }
   };
});

좋은! ngClick실제로 이미 처리 된 이벤트를 전파하고 싶지 않기 때문에 지시문의 이름을로 변경 했습니다.
maaartinus

1
조심해 일부 다른 플러그인은 실제로 해당 클릭을 듣고 싶어 할 수 있습니다. 외부를 클릭 할 때 닫히는 툴팁을 사용하면 외부 클릭이 본문으로 전파되지 않으므로 닫을 수 없습니다.
Jens

좋은 지적이지만이 문제는 지시어에서도 발생할 수 있습니다. 어쩌면 ignoreNgClick=true이벤트와 같은 속성을 추가 하고 처리해야 할 수도 있습니다 ... 어쨌든. 이상적으로는 원래 ngClick지시문에서 수정하는 것이 더럽습니다.
maaartinus

그렇습니다. 그래서 실제로 필요한 경우가 아니라면이 지시문을 사용하지 않는 이유입니다. 이 이유 때문에 클릭 전파를 계속하기 위해 다른 지시어를 작성해야했습니다. 그래서 분리 클릭 지시문이 있었고 부모님 몇 명은 계속 클릭 지시문이있었습니다. 이런 식으로 중간 요소에 대해서만 클릭을 건너 뛰었습니다.
Jens

1

나와 같은 지시문을 사용하는 경우 모델이나 컬렉션에서 속성을 업데이트 한 후 두 가지 데이터 바인딩 바인딩이 필요할 때 작동하는 방식입니다.

angular.module('yourApp').directive('setSurveyInEditionMode', setSurveyInEditionMode)

function setSurveyInEditionMode() {
  return {
    restrict: 'A',
    link: function(scope, element, $attributes) {
      element.on('click', function(event){
        event.stopPropagation();
        // In order to work with stopPropagation and two data way binding
        // if you don't use scope.$apply in my case the model is not updated in the view when I click on the element that has my directive
        scope.$apply(function () {
          scope.mySurvey.inEditionMode = true;
          console.log('inside the directive')
        });
      });
    }
  }
}

이제 모든 버튼, 링크, div 등에서 쉽게 사용할 수 있습니다.

<button set-survey-in-edition-mode >Edit survey</button>

-14
<ul class="col col-double clearfix">
 <li class="col__item" ng-repeat="location in searchLocations">
   <label>
    <input type="checkbox" ng-click="onLocationSelectionClicked($event)" checklist-model="selectedAuctions.locations" checklist-value="location.code" checklist-change="auctionSelectionChanged()" id="{{location.code}}"> {{location.displayName}}
   </label>



$scope.onLocationSelectionClicked = function($event) {
      if($scope.limitSelectionCountTo &&         $scope.selectedAuctions.locations.length == $scope.limitSelectionCountTo) {
         $event.currentTarget.checked=false;
      }
   };


7
이것이 왜 질문에 대한 답변이라고 생각하는지에 대한 설명을 추가 하시겠습니까?
paisanco

그것은 질문에 대한 답변입니다. 콜백에 이벤트를 전달하는 방법을 보여줍니다. 이는 초기 질문에서 파악한 것 이상입니다.
휴스턴
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.