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.
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.
Exercise: AngularJS Events
What replaces plain HTML's onclick attribute in AngularJS?