Event binding in Angular is a way to listen to user actions (like clicks, key presses, mouse movements, etc.) and run some component logic when those events happen.
In short, event binding connects the user’s actions (events) in the template to logic (methods/properties) in the component.
In this article, we will discuss the following three types of event-binding in Angular.
- Custom events binding
- Event binding via callbacks
- Event binding via shared service
Custom Events Binding
In Angular, you can create custom events for communication between child and parent components using @Output() and EventEmitter.
How It Works
In Child Component → Define an @Output() property and use EventEmitter to emit a custom event.
export class ChildComponentComponent {
@Output() childCustomEvent = new EventEmitter<string>();
triggerCustomEvent() {
const value = 'ASDF1234';
// Child emits event childCustomEvent.
this.childCustomEvent.emit(value);
}
}
In Parent Component Template → Bind to the child’s custom event using the same event-binding syntax ( ).
Parent listens to childCustomEvent and handles it as follows. $event carries the data sent from the child.
<div>
<h3>Parent Component</h3>
<p>Received Message from Child Component: {{ receivedMessage }}</p>
<app-child (childCustomEvent)="handleChildEvent($event)"></app-child>
</div>
In Parent Component Class → Handle the event data.
export class ParentComponentComponent {
receivedMessage: string = '';
// Handle the child custom event
handleChildEvent(message: string) {
this.receivedMessage = message;
}
}
Custom event binding in Angular lets child components communicate with parents using @Output() and EventEmitter.
Callback Method (parent passing a function to child)
Angular event binding via a callback method is a way of the parent passing a function to the child. This method works without using @Input for properties or @Output/EventEmitter for events. It is also called the callback pattern.
Compared to the custom events binding, in this method, the parent passes a function reference down to the child instead of the child emitting an event. The child can then call that function directly.
How It Works
The following code binds the child class’s onValueChange method to the parent’s handleValueChange method. This allows the parent to listen to changes emitted by the child. handleValueChange method will be called when the child emits a value.
Parent class
export class CallbackParentService {
message: string | null = null;
constructor(private callbackChildService: CallbackChildService) {
callbackChildService.onValueChange = this.handleValueChange.bind(this);
}
handleValueChange(value: string) {
this.message = value;
}
}
Child Class
triggerValueChange method will be called from outside to trigger the child event and then parent can listen to it.
export class CallbackChildService {
public onValueChange(value: string) {}
emitValue(value: string) {
this.onValueChange(value);
}
triggerValueChange(value: string) {
console.log('Child service triggering value change event.');
this.emitValue(value);
}
}
With Event-binding via callback, parent gives child a function, child executes it when an action happens.
Event binding via Shared Service
Another way to do event binding/communication in Angular is through a shared service.
This is often used for sibling components/classes or distant components/c;asses that don’t have a direct parent–child relationship.
How It Works
1. Create a shared service with a Subject/BehaviorSubject (from RxJS). next() method will emit value from shared service.
export class SharedService {
private dataSubject = new Subject<string>();
data$ = this.dataSubject.asObservable();
triggerValueChange(value: string) {
this.dataSubject.next(value);
}
}
2. Child/Sender service emits events through the shared service.
export class ChildService {
constructor(private sharedDataService: SharedService) {}
sendData(value: string) {
this.sharedDataService.triggerValueChange(value);
}
}
3. Parent/Receiver service subscribes to those events through the same service.
export class ParentService {
receivedData: string = '';
private subscription!: Subscription;
constructor(private sharedDataService: SharedService) {}
ngOnInit() {
this.subscription = this.sharedDataService.data$.subscribe((data) => {
this.receivedData = data;
});
}
ngOnDestroy() {
this.subscription?.unsubscribe(); // Prevent memory leaks
}
}
Note:
This service is a Singleton Service as it is provided in the root (providedIn: ‘root’), it lives as long as the application. Angular will not destroy it until the app itself is destroyed, so ngOnDestroy() won’t be called during normal navigation.
Event binding via shared service communicates through an RxJS stream in a service, instead of @Input/@Output or callbacks.
You can access the full code for the event-binding project here.