Question
In AngularJS, directives can use an & binding to receive and invoke a callback expression from a parent component. Can an Angular component receive a callback function through an @Input() and call it, as in this example? If so, what is the correct template syntax? If not, what is the closest Angular equivalent?
@Component({
selector: 'suggestion-menu',
template: `
<div (mousedown)="suggestionWasClicked(suggestion)">
...
</div>
`
})
export class SuggestionMenuComponent {
@Input() callback!: Function;
suggestionWasClicked(clickedEntry: SomeModel): void {
this.callback(clickedEntry, this.query);
}
}
<suggestion-menu callback="insertSuggestion"></suggestion-menu>
Short Answer
You can pass a function to an Angular child component using an @Input(), but the parent must use property binding: [callback]="insertSuggestion". In most Angular component APIs, the more idiomatic approach is for the child to emit an event with @Output() and for the parent to handle it with event binding.
Concept
Angular components communicate in two main directions:
- Parent to child: pass data or behavior through
@Input()properties. - Child to parent: notify the parent through
@Output()events.
A callback is a function that one piece of code receives now and runs later. A child component can receive a callback through an input and invoke it after a user action.
However, Angular generally favors @Output() for child-to-parent notifications. The child should describe what happened—for example, “a suggestion was selected”—rather than receive instructions about which parent method to call. This keeps the child reusable and makes its public API clear.
AngularJS & bindings accepted an expression that the directive evaluated in the parent scope. Angular does not use that scope-expression mechanism. Instead, Angular uses normal TypeScript values and template bindings: a function can be an input value, and an EventEmitter can publish an output event.
Mental Model
Think of a child component as a doorbell.
- An
@Input()callback is like giving the doorbell a phone number and telling it exactly whom to call. - An
@Output()event is like the doorbell making a chime. The parent chooses whether to listen and what to do when it hears the sound.
For reusable components, the chime model is usually better: the child announces an event, while the parent decides how to respond.
Syntax and Examples
A function input needs property binding with square brackets. Without brackets, Angular passes the literal text "insertSuggestion", not the function.
import { Component, Input } from '@angular/core';
interface SomeModel {
label: string;
}
@Component({
selector: 'suggestion-menu',
template: `
<button type="button" (click)="suggestionWasClicked(suggestion)">
Choose suggestion
</button>
`
})
export class SuggestionMenuComponent {
@Input({ required: true }) callback!: (entry: SomeModel, query: string) => void;
@Input() query = '';
@Input({ required: true }) suggestion!: SomeModel;
suggestionWasClicked(clickedEntry: SomeModel): void {
this.(clickedEntry, .);
}
}
Step by Step Execution
Consider this output-based example:
<suggestion-menu
[suggestion]="suggestion"
[query]="query"
(suggestionSelected)="insertSuggestion($event.entry, $event.query)">
</suggestion-menu>
selectSuggestion(entry: SomeModel): void {
this.suggestionSelected.emit({ entry, query: this.query });
}
Execution flow:
- Angular creates
SuggestionMenuComponent. - The parent passes
suggestionandqueryinto the child through input bindings. - The user clicks the child's button.
- The
(click)binding callsselectSuggestion(...)in the child. - The child emits a
suggestionSelectedevent containing the selected entry and query. - Angular receives that event in the parent template.
Real World Use Cases
Callback inputs can be useful when a child needs a small, configurable operation, such as:
- Providing a custom formatter for table values.
- Supplying a sorting or comparison function to a reusable list.
- Letting a data component call a supplied predicate to decide whether an item is allowed.
- Passing a strategy function to transform a value before display.
Outputs are usually better for user-driven component events, such as:
- A menu item was selected.
- A dialog was confirmed, cancelled, or closed.
- A file was chosen for upload.
- A pagination control moved to another page.
- A form control changed or submitted.
For example, a date picker can emit dateSelected, while its parent decides whether to save the date, validate it, or navigate elsewhere.
Real Codebase Usage
In production Angular applications, use these patterns:
- Use typed inputs. Prefer
(entry: SomeModel) => voidoverFunction. - Use outputs for notifications. Name outputs in the past tense, such as
saved,closed,selectionChanged, orsuggestionSelected. - Send a focused event payload. Emit only the information the parent needs.
- Validate required values. Use
@Input({ required: true })when a component cannot work without an input. - Use guard clauses. If a callback is optional, check it before calling it.
@Input() onRemove?: (id: string) => void;
remove(id: string): void {
if (!this.onRemove) {
return;
}
this.onRemove(id);
}
For an output, the child remains independent of parent behavior:
Common Mistakes
Passing a string instead of a function
This passes the text "insertSuggestion":
<!-- Incorrect for a callback input -->
<suggestion-menu callback="insertSuggestion"></suggestion-menu>
Use property binding to evaluate the parent expression:
<suggestion-menu [callback]="insertSuggestion"></suggestion-menu>
Using Function as the input type
// Avoid: accepts any callable value with no argument checking.
@Input() callback!: Function;
Use a function signature:
@Input({ required: true }) callback!: (entry: SomeModel, query: string) => void;
Comparisons
| Approach | Direction | Parent template syntax | Best for |
|---|---|---|---|
@Input() data | Parent → child | [query]="query" | Configuration and values the child needs |
@Input() callback | Parent → child, child invokes it | [callback]="insertSuggestion" | Custom algorithms, formatters, predicates, strategy functions |
@Output() with EventEmitter | Child → parent | (suggestionSelected)="insertSuggestion($event)" | User actions and component notifications |
AngularJS & binding | Directive evaluates parent expression |
Cheat Sheet
// Typed callback input
@Input({ required: true }) onSelect!: (item: Item) => void;
select(item: Item): void {
this.onSelect(item);
}
<!-- Function reference: square brackets are required -->
<app-list [onSelect]="handleSelect"></app-list>
// Preferred event output for child notifications
@Output() selected = new EventEmitter<Item>();
select(item: Item): void {
this.selected.emit(item);
}
<app-list (selected)=>
FAQ
Can Angular pass a function as an @Input()?
Yes. Bind a function reference with property binding: [callback]="myMethod".
Why does callback="myMethod" not work?
Without square brackets, Angular treats myMethod as a string attribute value rather than evaluating it as a parent component expression.
Should I use Function for an Angular callback input?
No. Use a specific type such as (item: Item) => void so TypeScript can check arguments and return values.
Is @Input() callback or @Output() better?
Use @Output() when the child reports that something happened. Use a callback input when the parent supplies a configurable behavior or algorithm that the child needs to run.
What is $event in an Angular output binding?
It is the value passed to emit(...) by the child component.
Why does this become undefined in my callback?
A normal method can lose its owning object when passed as a standalone function. Use an arrow-property method or bind the method to the parent instance.
Mini Project
Description
Build a small suggestion menu component that displays suggested labels and tells its parent which label the user selected. This models autocomplete menus, tag pickers, and search suggestion interfaces.
Goal
Create a reusable child component that emits a typed selection event and a parent component that updates its query text.
Requirements
- Create a child component that accepts an array of suggestion strings through an input.
- Create an output that emits the selected suggestion string.
- Render one button for each suggestion.
- Handle the output in the parent component.
- Update the parent query with the selected suggestion.
Keep learning
Related questions
@Directive vs @Component in Angular: Differences, Use Cases, and When to Use Each
Learn the difference between @Directive and @Component in Angular, including use cases, examples, and when to choose each.
Accessing Input Value from EventTarget in TypeScript
Learn why EventTarget has no value property in TypeScript and safely read values from HTML input events in Angular applications.
Angular (change) vs (ngModelChange): What’s the Difference?
Learn the difference between Angular (change) and (ngModelChange), when each fires, and which one to use in forms and inputs.