AngularJS 이벤트 전파 제어하기

AngularJS에서 이벤트 버블링, 캡처링을 이해하고 $event 객체로 전파를 제어하는 방법입니다. ng-click 중첩 시 발생하는 문제 해결법을 다룹니다.

1. 이벤트 전파 문제 상황

<!-- 문제: 버튼 클릭 시 부모 div의 click도 실행됨 -->
<div ng-click="parentClick()">
    부모 영역
    <button ng-click="buttonClick()">버튼</button>
</div>

2. $event.stopPropagation()

<!-- 이벤트 전파 중단 -->
<div ng-click="parentClick()">
    부모 영역
    <button ng-click="buttonClick(); $event.stopPropagation()">
        버튼
    </button>
</div>

<!-- 또는 컨트롤러에서 처리 -->
<button ng-click="buttonClick($event)">버튼</button>

// Controller
$scope.buttonClick = function($event) {
    $event.stopPropagation();
    // 버튼 로직
};

3. $event.preventDefault()

<!-- 기본 동작 방지 -->
<a href="/page" ng-click="handleClick($event)">링크</a>

$scope.handleClick = function($event) {
    $event.preventDefault();  // 페이지 이동 방지
    // 커스텀 로직
};

<!-- 폼 제출 방지 -->
<form ng-submit="submitForm($event)">
    <button type="submit">제출</button>
</form>

$scope.submitForm = function($event) {
    $event.preventDefault();
    // AJAX 처리
};

4. 이벤트 객체 속성

$scope.handleEvent = function($event) {
    console.log($event.target);        // 이벤트 발생 요소
    console.log($event.currentTarget); // 핸들러가 연결된 요소
    console.log($event.type);          // 이벤트 타입 (click 등)
    console.log($event.pageX);         // 마우스 X 좌표
    console.log($event.pageY);         // 마우스 Y 좌표
    console.log($event.keyCode);       // 키보드 키 코드
};

5. 실전 예시: 테이블 행 클릭

<!-- 행 클릭 시 상세보기, 버튼은 삭제 -->
<tr ng-repeat="item in items" ng-click="viewDetail(item)">
    <td>{{item.name}}</td>
    <td>{{item.price | number}}</td>
    <td>
        <button ng-click="deleteItem(item, $event)">삭제</button>
    </td>
</tr>

$scope.deleteItem = function(item, $event) {
    $event.stopPropagation(); // 행 클릭 방지
    // 삭제 로직
};

6. 드롭다운 메뉴

<!-- 메뉴 외부 클릭 시 닫기 -->
<div ng-click="closeMenu()">
    <div class="dropdown" ng-click="$event.stopPropagation()">
        <button ng-click="toggleMenu()">메뉴</button>
        <ul ng-show="menuOpen">
            <li ng-click="selectItem(1)">항목 1</li>
            <li ng-click="selectItem(2)">항목 2</li>
        </ul>
    </div>
</div>

7. 이벤트 위임 패턴

<!-- 부모에서 이벤트 처리 -->
<ul ng-click="handleListClick($event)">
    <li ng-repeat="item in items" data-id="{{item.id}}">
        {{item.name}}
    </li>
</ul>

$scope.handleListClick = function($event) {
    var target = angular.element($event.target);
    var id = target.attr("data-id");
    if (id) {
        // 해당 아이템 처리
    }
};

stopPropagation vs preventDefault

메서드역할예시
stopPropagation버블링/캡처링 중단부모 클릭 방지
preventDefault기본 동작 방지링크 이동 방지
둘 다 사용전파 + 기본 방지폼 제출 커스텀