$scope.$emit in modern Angular
$emit sent an event up through every ancestor scope. An output() reaches only the direct parent, with a typed payload.
Before · AngularJS
// child controller
$scope.$emit('item:selected', item);
// some ancestor controller
$scope.$on('item:selected', function (event, item) {
event.stopPropagation();
vm.selected = item;
});After · Angular// item-row.component.ts
export class ItemRowComponent {
item = input.required<Item>();
selected = output<Item>();
}
// its template
<button (click)="selected.emit(item())">Select</button>
// parent template
@for (item of items(); track item.id) {
<app-item-row [item]="item" (selected)="current.set($event)" />
}What changes
- Outputs do not bubble: a grandparent that needs the event must receive it from the parent or from a service.
- The event name string becomes a typed property, so the compiler finds every emitter and every listener.
- event.stopPropagation() is no longer needed, because nothing travels further than the parent.
Migration tip. List each $emit event and who listens to it. If the listener is the direct parent, use an output; if it is several levels up, use a service declared in that ancestor's providers, which keeps the event limited to its subtree.
Related
- nested ng-controller and scope inheritance
- ngMock unit tests (module, inject, $controller)
- $httpBackend
- $attrs.$observe
Planning a migration or a micro-frontend platform?
In a 20-minute call you describe your situation and I tell you how I'd approach it. If it isn't worth doing yet, I'll say so.
Message me on LinkedIn