Components
|
This section documents modern, standalone Angular — signals, the built-in This content was generated with the assistance of AI and should be verified against angular.dev before being relied on in production. Angular ships a major release roughly every six months and its APIs continue to evolve: the examples here target the current major release; where a consulted source disagrees with the current documentation, the documentation wins and the difference is noted. This section’s bibliography lists the reference material consulted while preparing these pages. |
A component is a TypeScript class with an @Component decorator that pairs a template with the logic and state
that drive it. Components are the only building block you need to compose an Angular UI; every screen is a tree
of them.
@Component metadata
The decorator’s configuration object describes how Angular compiles and renders the class. The common fields:
-
selector— the CSS selector that marks where this component mounts in a template. -
template(inline) ortemplateUrl(a separate.htmlfile). -
styles(inline) orstyleUrl/styleUrls(separate stylesheet files). -
standalone— defaults totrue; a standalone component manages its own dependencies and does not belong to anNgModule. -
imports— the other components, directives, and pipes this template uses. -
host— bindings and listeners applied to the component’s own host element.
import { Component, signal } from '@angular/core';
@Component({
selector: 'app-counter',
imports: [],
template: `
<p>Count: {{ count() }}</p>
<button (click)="increment()">+1</button>
`,
styles: `
:host { display: inline-flex; gap: .5rem; }
button { font: inherit; }
`,
})
export class Counter {
readonly count = signal(0);
increment(): void {
this.count.update((n) => n + 1);
}
}
See Components for the full metadata reference.
The component class and the render tree
Angular instantiates one object of the component class per place the selector appears. That instance owns the
template’s state; the template reads it through bindings and calls its methods from event handlers. Nesting
components — by putting one component’s selector in another’s template — builds a render tree rooted at the
component passed to bootstrapApplication.
Selectors come in three forms:
@Component({ selector: 'app-card', /* ... */ }) // element: <app-card>
@Component({ selector: '[appHighlight]', /* ... */ }) // attribute: <div appHighlight>
@Component({ selector: '.app-toolbar', /* ... */ }) // class: <div class="app-toolbar">
Element selectors are the norm for components; attribute selectors are typical for directives. See component selectors.
Styling and view encapsulation
Styles declared in styles / styleUrl are scoped to the component by default. Angular’s
ViewEncapsulation setting controls how:
-
Emulated(default) — Angular rewrites selectors and adds per-component attributes so the styles do not leak out or in. No native Shadow DOM. -
None— styles are added to the document<head>as-is and apply globally. -
ShadowDom— the component renders into a real shadow root; browser-native style isolation.
import { Component, ViewEncapsulation } from '@angular/core';
@Component({
selector: 'app-badge',
template: `<span class="dot"></span><ng-content />`,
styleUrl: './badge.scss',
encapsulation: ViewEncapsulation.Emulated,
})
export class Badge {}
:host {
display: inline-block;
}
:host(.danger) .dot { // host element that also has the .danger class
background: red;
}
:host-context(.dark-theme) { // an ancestor anywhere has .dark-theme
color: #eee;
}
::ng-deep .legacy-child { // deprecated: pierces into child components
margin: 0;
}
:host targets the component’s own element, :host-context() styles it based on an ancestor, and ::ng-deep
forces a style through to descendants — it is deprecated; prefer exposing a CSS custom property or moving the
rule to src/styles.css, the global stylesheet listed in angular.json. See
styling components.
Host elements
Every component instance has a host element — the DOM element its selector matched. Bind to it and listen on
it through host metadata, and compose behaviour onto it with hostDirectives:
import { Component } from '@angular/core';
import { Tooltip } from './tooltip';
@Component({
selector: 'app-icon-button',
template: `<ng-content />`,
host: {
'role': 'button',
'tabindex': '0',
'[class.is-active]': 'active()',
'(keydown.enter)': 'activate()',
},
hostDirectives: [Tooltip],
})
export class IconButton {
// active(), activate() defined here
}
hostDirectives applies Tooltip to every <app-icon-button> without the template opting in. See
host elements.
Rendering components programmatically
When the component to show is only known at runtime, render it from code rather than from a static selector.
NgComponentOutlet does it declaratively in a template:
<ng-container *ngComponentOutlet="currentWidget()" />
ViewContainerRef.createComponent does it imperatively:
import { Component, ViewContainerRef, inject } from '@angular/core';
import { ChartWidget } from './chart-widget';
@Component({ selector: 'app-dashboard', template: `` })
export class Dashboard {
private readonly vcr = inject(ViewContainerRef);
show(): void {
const ref = this.vcr.createComponent(ChartWidget);
ref.setInput('title', 'Sales');
// ref.destroy() to remove it
}
}