AngularJS Events

Learn how AngularJS's built-in event directives let you respond to user interactions like clicks, input changes, and mouse movement directly in your HTML.

Handling Events with Directives

Instead of calling addEventListener in JavaScript, AngularJS lets you wire up event handling declaratively in the template with ng-* event directives. Each directive attaches a native browser event listener behind the scenes and, when it fires, evaluates the AngularJS expression you gave it against the current scope - typically a call to a controller function.

DirectiveFires When
ng-clickThe element is clicked
ng-dblclickThe element is double-clicked
ng-changeA model bound with ng-model changes value (inputs, selects, checkboxes)
ng-mouseoverThe mouse pointer enters the element
ng-mouseleaveThe mouse pointer leaves the element
ng-keyupA keyboard key is released while the element has focus
ng-submitA form is submitted
ng-focus / ng-blurThe element gains or loses focus

Example

<!DOCTYPE html>
<html>
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
</head>
<body>

<div ng-app="eventApp" ng-controller="CounterController as vm">
  <p>Clicks: {{ vm.count }}</p>
  <button ng-click="vm.count = vm.count + 1">Click me</button>
  <button ng-click="vm.count = 0">Reset</button>
</div>

<script>
angular.module('eventApp', [])
  .controller('CounterController', function() {
    var vm = this;
    vm.count = 0;
  });
</script>

</body>
</html>

Passing Data and Using $event

Event directives can call a controller function with arguments, including the item currently being iterated by ng-repeat. AngularJS also injects a special $event variable holding the native DOM event object, so a handler can call methods like stopPropagation() or preventDefault() when needed.

Example

<!DOCTYPE html>
<html>
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
</head>
<body>

<div ng-app="eventApp" ng-controller="ListController as vm">
  <ul>
    <li ng-repeat="item in vm.items"
        ng-mouseover="vm.hovered = item"
        ng-mouseleave="vm.hovered = null"
        ng-click="vm.selectItem(item, $event)"
        ng-class="{ hovered: vm.hovered === item }">
      {{ item.label }}
    </li>
  </ul>
  <p ng-if="vm.selected">You picked: {{ vm.selected.label }}</p>
</div>

<script>
angular.module('eventApp', [])
  .controller('ListController', function() {
    var vm = this;
    vm.items = [{ label: 'Apples' }, { label: 'Bananas' }, { label: 'Cherries' }];
    vm.selectItem = function(item, $event) {
      $event.stopPropagation();
      vm.selected = item;
    };
  });
</script>

</body>
</html>

ng-change is a special case: it never fires on its own. It must sit on an element that also has ng-model, and it runs only after the user's interaction changes that model's value - not when the model is changed programmatically from controller code.

Example

<!DOCTYPE html>
<html>
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
</head>
<body>

<div ng-app="eventApp" ng-controller="ListController as vm">
  <select ng-model="vm.category" ng-change="vm.filterByCategory()">
    <option value="">All</option>
    <option value="fruit">Fruit</option>
    <option value="veg">Vegetable</option>
  </select>

  <ul>
    <li ng-repeat="item in vm.visibleItems">{{ item.label }}</li>
  </ul>
</div>

<script>
angular.module('eventApp', [])
  .controller('ListController', function() {
    var vm = this;
    vm.items = [{ label: 'Apples' }, { label: 'Bananas' }, { label: 'Cherries' }];
    vm.visibleItems = vm.items;

    // Added to the ListController above:
    vm.filterByCategory = function() {
      vm.visibleItems = vm.category
        ? vm.items.filter(function(i) { return i.type === vm.category; })
        : vm.items;
    };
  });
</script>

</body>
</html>
  • Prefer calling a controller function (ng-click="vm.save()") over writing complex logic directly in the HTML expression.
  • Pair ng-change with ng-model - ng-change only fires alongside a model change, never on its own.
  • Use $event.stopPropagation() or $event.preventDefault() inside handler functions when you need to control event bubbling or default browser behavior.
Note: Keep event handler expressions short - a single method call - and put the actual logic inside the controller or a service so it stays easy to read and to test.
Note: ng-change does not fire when the model is updated from JavaScript (for example, vm.category = 'fruit' inside a controller). It only fires when the user changes the value through the bound element itself.

Exercise: AngularJS Events

What replaces plain HTML's onclick attribute in AngularJS?