Angular Components: Building Blocks of Your App
The Big Picture: Components are LEGO Bricks
Imagine you’re building a house with LEGO bricks. Each brick has a specific shape, color, and purpose. Some bricks make doors, some make windows, some make roofs.
Angular components work exactly the same way!
Each component is a self-contained piece of your app with:
- Its own look (template)
- Its own style (CSS)
- Its own brain (TypeScript logic)
When you put many components together, you build an entire application!
Component Fundamentals
What IS a Component?
A component is like a recipe card with three parts:
- What it looks like (HTML template)
- How it’s styled (CSS)
- What it does (TypeScript class)
// A simple component has 3 parts
@Component({
selector: 'app-greeting',
template: '<h1>Hello!</h1>',
styles: ['h1 { color: blue; }']
})
export class GreetingComponent { }
Think of it like this:
- Template = The face (what users see)
- Styles = The clothes (how it looks)
- Class = The brain (what it thinks and does)
The @Component Decorator
What’s a Decorator?
A decorator is like a name tag you put on a class. It tells Angular: “Hey! This isn’t just any class. It’s a special COMPONENT!”
The @Component() decorator sits right above your class:
@Component({
// Settings go here
})
export class MyComponent { }
The Decorator’s Settings
The decorator takes an object with settings:
| Setting | Purpose | Example |
|---|---|---|
selector |
The name you use in HTML | 'app-button' |
template |
The HTML content | '<button>Click</button>' |
templateUrl |
Link to HTML file | './button.html' |
styles |
CSS rules | ['button { color: red }'] |
styleUrls |
Link to CSS files | ['./button.css'] |
standalone |
Is it independent? | true or false |
Component Selectors
Your Component’s Name Tag
The selector is the name you give your component. It’s how you use it in HTML!
@Component({
selector: 'app-welcome', // This is the name
template: '<p>Welcome!</p>'
})
export class WelcomeComponent { }
Now use it in HTML:
<app-welcome></app-welcome>
Selector Rules
- Always start with a prefix (like
app-) - Use lowercase and dashes
- Make it descriptive
graph TD A[selector: 'app-user-card'] --> B["#60;app-user-card#62;#60;/app-user-card#62;"] B --> C[Component renders here!]
Good selectors:
app-user-profileapp-shopping-cartapp-nav-menu
Bad selectors:
userprofile(no prefix)APP-CART(uppercase)
Component Templates
The Face of Your Component
The template is the HTML that shows on screen. You have two ways to define it:
Option 1: Inline Template
For small components, write HTML directly:
@Component({
selector: 'app-hello',
template: '<h1>Hello, World!</h1>'
})
export class HelloComponent { }
For multiple lines, use backticks:
@Component({
selector: 'app-card',
template: `
<div class="card">
<h2>Title</h2>
<p>Content here</p>
</div>
`
})
export class CardComponent { }
Option 2: External Template File
For bigger components, use a separate file:
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html'
})
export class DashboardComponent { }
When to Use Which?
| Situation | Use |
|---|---|
| Less than 5 lines of HTML | template (inline) |
| More than 5 lines | templateUrl (file) |
| Complex layouts | templateUrl (file) |
Component Styles
Dressing Up Your Component
Every component can have its own styles. Just like templates, you have two options:
Option 1: Inline Styles
@Component({
selector: 'app-button',
template: '<button>Click Me</button>',
styles: [`
button {
background: purple;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
}
`]
})
export class ButtonComponent { }
Option 2: External Style Files
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent { }
The Magic Part
Your styles are private to your component! A style in one component won’t accidentally change another component.
graph TD A[Component A<br>h1 { color: red }] --> B[Only A's h1 is red] C[Component B<br>h1 { color: blue }] --> D[Only B's h1 is blue] B --> E[They don't conflict!] D --> E
View Encapsulation
The Invisible Shield
View encapsulation is like putting each component in its own bubble. Styles inside the bubble can’t escape. Styles outside can’t get in!
Three Types of Encapsulation
import { ViewEncapsulation } from '@angular/core';
@Component({
selector: 'app-example',
template: '<p>Hello</p>',
styles: ['p { color: red; }'],
encapsulation: ViewEncapsulation.Emulated
})
| Type | What It Does |
|---|---|
Emulated |
Default. Adds unique IDs to scope styles |
None |
No bubble. Styles become global |
ShadowDom |
Uses browser’s Shadow DOM |
Example: Emulated (Default)
Angular adds special attributes to keep styles private:
<!-- What you write -->
<p>Hello</p>
<!-- What Angular creates -->
<p _ngcontent-xyz>Hello</p>
And your CSS becomes:
p[_ngcontent-xyz] { color: red; }
This is why your styles stay contained!
Standalone Components
The Independent Heroes
Standalone components are the new, simpler way to build in Angular!
Old way: You needed modules (NgModule) to organize components.
New way: Components can work independently!
@Component({
selector: 'app-hero',
standalone: true, // I'm independent!
template: '<h1>I am a Hero!</h1>'
})
export class HeroComponent { }
Why Standalone is Great
graph TD A[Old Way] --> B[Create Component] B --> C[Create Module] C --> D[Register Component in Module] D --> E[Import Module Elsewhere] F[New Way: Standalone] --> G[Create Component] G --> H[Import Directly Where Needed]
Less files. Less confusion. More simple!
Component Imports
Sharing is Caring
When your standalone component needs to use other things (like other components, directives, or pipes), you import them:
@Component({
selector: 'app-todo-list',
standalone: true,
imports: [
CommonModule, // For *ngIf, *ngFor
FormsModule, // For form handling
TodoItemComponent // Another component!
],
template: `
<div *ngFor="let todo of todos">
<app-todo-item [task]="todo">
</app-todo-item>
</div>
`
})
export class TodoListComponent {
todos = ['Learn Angular', 'Build App'];
}
What Can You Import?
| Import | Purpose |
|---|---|
CommonModule |
Basic directives (*ngIf, *ngFor) |
FormsModule |
Template-driven forms |
ReactiveFormsModule |
Reactive forms |
RouterModule |
Routing features |
| Other components | To use them in template |
Real Example
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HeaderComponent } from './header';
import { FooterComponent } from './footer';
@Component({
selector: 'app-page',
standalone: true,
imports: [
CommonModule,
HeaderComponent,
FooterComponent
],
template: `
<app-header></app-header>
<main>Page content</main>
<app-footer></app-footer>
`
})
export class PageComponent { }
Putting It All Together
Here’s a complete component with everything we learned:
import { Component, ViewEncapsulation }
from '@angular/core';
import { CommonModule } from '@angular/common';
@Component({
// The name tag
selector: 'app-greeting-card',
// It's independent!
standalone: true,
// What it needs
imports: [CommonModule],
// What it looks like
template: `
<div class="card">
<h2>{{ title }}</h2>
<p *ngIf="showMessage">
{{ message }}
</p>
</div>
`,
// How it's styled
styles: [`
.card {
padding: 20px;
border-radius: 10px;
background: #f0f0f0;
}
`],
// Style protection
encapsulation: ViewEncapsulation.Emulated
})
export class GreetingCardComponent {
title = 'Welcome!';
message = 'Happy to see you!';
showMessage = true;
}
Quick Summary
| Concept | What It Does |
|---|---|
| Component | Self-contained building block |
| @Component | Decorator that defines a component |
| Selector | The HTML tag name |
| Template | The HTML (inline or file) |
| Styles | The CSS (inline or file) |
| Encapsulation | Keeps styles private |
| Standalone | Independent, no module needed |
| Imports | Other things the component uses |
You now understand the building blocks of Angular! Each component is a small, reusable piece that you can combine to build amazing applications.
Next step: Start creating your own components and see them come to life!