Angular Components
Components are the fundamental building blocks of Angular applications. Each component encapsulates the template, styles, and behavior for a part of your user interface.
Component Structure
An Angular component consists of:
- A TypeScript class with a
@Component decorator
- An HTML template (inline or external)
- Optional CSS styles
- Component metadata (selector, imports, etc.)
Basic Component Example
Here’s a simple component from the application:
import { Component, signal } from '@angular/core';
@Component({
templateUrl: './hero-page.component.html'
})
export class HeroPageComponent {
name = signal('Ironman');
age = signal(45);
getHeroDescription() {
return `${this.name()} - ${this.age()}`;
}
changeHero() {
this.name.set('spiderman');
this.age.set(22);
}
changeAge() {
this.age.set(60);
}
resetForm() {
this.name.set('Ironman');
this.age.set(45);
}
}
Source: src/app/pages/hero/hero-page.component.ts:1-24
Component Decorator
The @Component decorator provides metadata about the component:
Required Properties
@Component({
templateUrl: './counter-page.html',
styles: `
button {
padding: 5px;
margin: 5px 10px;
width: 75px;
}
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
Source: src/app/pages/counter/counter-page.ts:3-13
Template Options
Choose between external or inline templates:
// External template file
@Component({
templateUrl: './hero-page.component.html'
})
// Inline template
@Component({
template: `
<h1>{{ title }}</h1>
<p>Content here</p>
`
})
Style Options
Add component-specific styles:
// Inline styles
@Component({
styles: `
button {
padding: 5px;
margin: 5px 10px;
width: 75px;
}
`
})
// External stylesheet
@Component({
styleUrl: './component.css'
})
// Multiple stylesheets
@Component({
styleUrls: ['./component.css', './theme.css']
})
Component styles are scoped by default. They only apply to the component’s template, not to child components or the rest of the application.
Standalone Components
Modern Angular components use standalone mode, which eliminates the need for NgModules:
import { Component, signal } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { Navbar } from "./components/shared/navbar/navbar";
@Component({
selector: 'app-root',
imports: [RouterOutlet, Navbar],
templateUrl: './app.html',
})
export class App {
protected readonly title = signal('Miguel');
}
Source: src/app/app.ts:1-13
Imports Array
The imports array declares dependencies directly in the component:
@Component({
selector: 'app-navbar',
imports: [RouterLink, RouterLinkActive],
templateUrl: './navbar.html',
})
export class Navbar {}
Source: src/app/components/shared/navbar/navbar.ts:4-8
Standalone Benefits:
- Simpler dependency management
- No NgModule boilerplate
- Better tree-shaking and bundle optimization
- Easier to understand component dependencies
- Recommended for new Angular applications
Component Selector
The selector defines the custom HTML tag:
@Component({
selector: 'app-root',
imports: [RouterOutlet, Navbar],
templateUrl: './app.html',
})
export class App {
protected readonly title = signal('Miguel');
}
Use it in templates:
Component Class
The TypeScript class contains the component’s logic:
Properties
Define reactive state with signals:
export class DragonballSuperPage {
name = signal('');
power = signal(0);
characters = signal<Character[]>([
{ id: 1, name: 'Goku', power: 9001 },
{ id: 2, name: 'Vegeta', power: 8000 },
]);
}
Source: src/app/pages/dragonball-super/dragonball-super-page.ts:14-20
Methods
Implement component behavior:
export class DragonballSuperPage {
addCharacter() {
// Validation
if (!this.name().trim() || this.power() <= 0) {
return;
}
const newCharacter: Character = {
id: this.characters().length + 1,
name: this.name(),
power: this.power(),
};
// Update signal
this.characters.update(chars => [...chars, newCharacter]);
}
}
Source: src/app/pages/dragonball-super/dragonball-super-page.ts:22-36
Component Templates
Templates define the component’s HTML structure:
Data Binding
<!-- Interpolation -->
<h1>{{ name() }}</h1>
<!-- Property binding -->
<input [value]="name()">
<!-- Event binding -->
<button (click)="changeHero()">Cambiar nombre</button>
<!-- Two-way binding -->
<input [(ngModel)]="name">
Source: src/app/pages/hero/hero-page.component.html:1-24
Calling Signal Values
<h1>{{ name() }}</h1>
<dl>
<td>Nombre:</td>
<dd>{{ name() }}</dd>
<td>Edad:</td>
<dd>{{ age() }}</dd>
<td>Método:</td>
<dd>{{ getHeroDescription() }}</dd>
<td>Capitalizado:</td>
<dd>{{ name().toUpperCase() }}</dd>
</dl>
Component Communication
Parent to Child
Use @Input() to pass data:
import { Component, input } from '@angular/core';
@Component({
selector: 'app-child',
template: '<p>{{ data() }}</p>'
})
export class ChildComponent {
data = input<string>();
}
Child to Parent
Use @Output() to emit events:
import { Component, output } from '@angular/core';
@Component({
selector: 'app-child',
template: '<button (click)="notify()">Click</button>'
})
export class ChildComponent {
clicked = output<void>();
notify() {
this.clicked.emit();
}
}
Application Bootstrap
Bootstrap your root component:
import { bootstrapApplication } from '@angular/platform-browser';
import { appConfig } from './app/app.config';
import { App } from './app/app';
bootstrapApplication(App, appConfig)
.catch((err) => console.error(err));
Source: src/main.ts:1-6
The root component (typically App) must be bootstrapped using bootstrapApplication() for standalone components.
Component Lifecycle
Common lifecycle hooks:
import { Component, OnInit, OnDestroy } from '@angular/core';
export class MyComponent implements OnInit, OnDestroy {
ngOnInit() {
// Initialize component
}
ngOnDestroy() {
// Cleanup before component is destroyed
}
}
Best Practices
Component Design Tips:
- Use standalone components for new development
- Keep components focused on a single responsibility
- Use signals for reactive state management
- Import only what you need in the imports array
- Use OnPush change detection with signals for better performance
- External templates for complex HTML, inline for simple components
- Scope styles to components to avoid conflicts
Next Steps