Angular Components

Components are the fundamental building blocks of an Angular application, each pairing a TypeScript class with an HTML template to render and control a piece of UI.

What Is a Component?

An Angular component is a class decorated with @Component that tells Angular how to render a piece of the screen. The class holds the state and behavior; the template describes the markup that state produces. Every screen you see in an Angular app, from a single button to an entire dashboard, is built by composing components inside other components.

Anatomy of a Standalone Component

Modern Angular components are standalone by default, meaning they declare their own dependencies through an imports array instead of belonging to an NgModule. A minimal component needs three things: a selector that names the custom HTML tag, a template that defines the markup, and the class body itself.

A minimal standalone component

import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';

@Component({
  selector: 'app-greeting',
  standalone: true,
  template: `<h2>Hello, {{ name }}!</h2>`
})
export class GreetingComponent {
  name = 'Angular developer';
}

bootstrapApplication(GreetingComponent).catch(err => console.error(err));

The @Component Decorator, Field by Field

The decorator's metadata object is where most of a component's identity lives. The table below covers the properties you will reach for on nearly every component you write.

PropertyPurpose
selectorThe custom HTML tag used to place the component in a parent template, e.g. app-greeting.
standaloneMarks the component as not requiring an NgModule; true by default in modern Angular.
template / templateUrlInline markup string or a path to an external .html file.
styleUrl / styleUrlsPath to one or more CSS files scoped to this component.
importsOther standalone components, directives, or pipes this template depends on.

A component that imports another component

import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';

// GreetingComponent would normally live in its own file, ./greeting.component.ts.
// It is inlined here so this example is a single, self-contained, runnable file.
@Component({
  selector: 'app-greeting',
  standalone: true,
  template: `<h2>Hello, {{ name }}!</h2>`
})
export class GreetingComponent {
  name = 'Angular developer';
}

@Component({
  selector: 'app-dashboard',
  standalone: true,
  imports: [GreetingComponent],
  template: `
    <app-greeting></app-greeting>
    <p>Widgets loaded: {{ widgetCount }}</p>
  `
})
export class DashboardComponent {
  widgetCount = 4;
}

bootstrapApplication(DashboardComponent).catch(err => console.error(err));

Templates and Selectors

A selector is just a CSS-style tag name, so it must be unique across your application to avoid one component silently shadowing another. Angular's style guide recommends a short, project-specific prefix so third-party libraries never collide with your own tags.

  • Prefix selectors with a short app identifier, e.g. app- or acme-.
  • Keep templates focused; extract a child component once markup grows past a screenful.
  • Prefer templateUrl and styleUrl for anything longer than a few lines of markup.
  • Name files consistently: greeting.component.ts, greeting.component.html, greeting.component.css.

Composing components with a shared child

import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';

// GreetingComponent would normally live in its own file, ./greeting.component.ts.
// It is inlined here so this example is a single, self-contained, runnable file.
@Component({
  selector: 'app-greeting',
  standalone: true,
  template: `<h2>Hello, {{ name }}!</h2>`
})
export class GreetingComponent {
  name = 'Angular developer';
}

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [GreetingComponent],
  template: `
    <header><h1>My Angular App</h1></header>
    <app-greeting></app-greeting>
    <app-greeting></app-greeting>
  `
})
export class AppComponent {}

bootstrapApplication(AppComponent).catch(err => console.error(err));
Note: Since Angular 17, standalone: true is the default for anything generated with the CLI, so you can omit the flag entirely in new projects — it is shown above only for clarity.
Note: Two components sharing the same selector will not both fail to compile, but only one definition wins at runtime, which produces confusing bugs. Always double-check selector names when copying a component as a starting point for a new one.

Exercise: Angular Components

Which decorator marks a class as an Angular component?