Skip to content

Angular Components Output

Understanding the core of Angular

Every Angular component must have:

  • TypeScript class that describes the behaviors,
  • HTML template that controls what renders into the DOM,
  • CSS selector that defines how the component is used in HTML (optional, could also use a global).

You provide Angular-specific information for a component by adding the @Component decorator on top of the TypeScript class. The object passed to the @Component decorator is called the component’s metadata.

my-component.ts
@Component({ /* component's metadata */
selector: 'app-my-component',
template: `<img src="profile-photo.jpg" alt="Your profile photo" />`,
styles: `
img {
border-radius: 50%;
}
`,
})
export class MyComponent {}

Usually, HTML template and CSS classes are in a separate files:

my-component.ts
import {Component, input} from '@angular/core';
@Component({ /* component's metadata */
selector: 'app-my-component',
templateUrl: 'my-component.html',
styleUrl: 'my-component.css',
})
export class MyComponent {}

To use a component, directive, or pipe, you must add it to the imports array in the @Component decorator:

out-component.ts
import {Component, input} from '@angular/core';
import {MyComponent} from './my-component';
@Component({
imports: [MyComponent],
selector: 'app-out-component',
template: `
<h1>Out Component</h1>
<app-my-component><app-my-component />
`,
})
export class OutComponent {}

Import MyComponent component in order to use it in OutComponent component’s template.

Angular components can define custom events by assigning a property to the output function:

my-panel.ts
@Component({/*...*/})
export class MyPanel {
panelClosed = output<void>();
}

The above component is associated to the following template:

my-panel.html
<expandable-panel (panelClosed)="savePanelState()" />

The output function returns an OutputEmitterRef.

You can emit an event by calling emit() method on the OutputEmitterRef:

this.panelClosed.emit();

Angular refers to properties initialized with output function as outputs. You can use outputs to raise custom events.

Angular custom events do not bubble up the DOM

When extending a component class, outputs are inherited by the child class. You can exclusively call output in component and directive property initializers.

You can pass event data when calling emit:

// emit primitive values.
this.valueChanged.emit(7);
// emit custom event objects
this.thumbDropped.emit({
pointerX: 123,
pointerY: 456,
});

When defining an event listener in a template, you can access the event data from the $event variable:

my-slider.html
<my-slider (valueChanged)="logValue($event)" />

Receive the event data in the parent component:

app.ts
@Component({/*...*/})
export class App {
logValue(value: number) {
/*...*/
}
}

The output function accepts a parameter that lets you specify a different name for the event in a template:

my-slider.ts
@Component({/*...*/})
export class CustomSlider {
changed = output({alias: 'valueChanged'});
}

With the template:

my-slider.html
<my-slider (valueChanged)="saveVolume()" />

This alias does not affect usage of the property in TypeScript code.

While you should generally avoid aliasing outputs for components, this feature can be useful for renaming properties while preserving an alias for the original name or for avoiding collisions with the name of native DOM events.

When creating a component dynamically, you can programmatically subscribe to output events from the component instance. OutputRef type includes a subscribe method:

const someComponentRef: ComponentRef<SomeComponent> = viewContainerRef.createComponent(/*...*/);
someComponentRef.instance.someEventProperty.subscribe((eventData) => {
console.log(eventData);
});

Angular automatically cleans up event subscriptions when it destroys components with subscribers. Alternatively, you can manually unsubscribe from an event.

The subscribe function returns an OutputRefSubscription with an unsubscribe method:

const eventSubscription = someComponent.someEventProperty.subscribe((eventData) => {
console.log(eventData);
});
// ...
eventSubscription.unsubscribe();

Avoid choosing output names that collide with events on DOM elements like HTMLElement. Name collisions introduce confusion about whether the bound property belongs to the component or the DOM element.

Avoid adding prefixes for component outputs like you would with component selectors. Since a given element can only host one component, any custom properties can be assumed to belong to the component.

Always use camelCase output names. Avoid prefixing output names with "on".

You can alternatively define custom events by assigning a property to a new EventEmitter and adding @Output decorator:

my-panel.ts
@Component({/*...*/})
export class MyPanel {
@Output() panelClosed = new EventEmitter<void>();
}

You can emit an event by calling the emit method on the EventEmitter.

@Output decorator accepts a parameter that lets you specify a different name for the event in a template:

my-slider.ts
@Component({/*...*/})
export class MySlider {
@Output('valueChanged') changed = new EventEmitter<number>();
}

The above component is associated to the following template:

my-slider.html
<my-slider (valueChanged)="saveVolume()" />

This alias does not affect usage of the property in TypeScript code.

In addition to the @Output decorator, you can also specify a component’s outputs with the outputs property within @Component decorator. This can be useful when a component inherits a property from a base class:

my-slider.ts
// `MySlider` inherits `valueChanged` property from `BaseSlider`.
@Component({
/*...*/
outputs: ['valueChanged'],
})
export class MySlider extends BaseSlider {}

You can additionally specify an output alias in the outputs list by putting the alias after a colon in the string:

my-slider.ts
// `CustomSlider` inherits the `valueChanged` property from `BaseSlider`.
@Component({
/*...*/
outputs: ['valueChanged: volumeChanged'],
})
export class MySlider extends BaseSlider {}