Day 2 β Mastering Angular Components, Templates & Data Binding
π Day 2 β Mastering Angular Components, Templates & Data Binding
Hands-on Angular tutorial β Part of the Zero to Hero Series
Welcome to Day 2, where we dig into the heart of Angular:
- βοΈ Components
- βοΈ Templates
- βοΈ Data binding
- βοΈ Events
- βοΈ Inputs & outputs
- βοΈ Signals in components
Today, youβll understand how Angular actually builds UI, and youβll build three interactive components to practice.
Ready? Letβs code! π
π¦ What You Will Build Today
By the end of this tutorial, youβll build:
- 1οΈβ£ A
ProfileCardcomponent - 2οΈβ£ A
Countercomponent (with signals) - 3οΈβ£ A Two-way binding demo
- 4οΈβ£ Parent β Child communication
All in real Angular code, no theory-only fluff.
π§ 1. What is a Component?
A component is basically:
- HTML template
- TypeScript logic
- Styling
- Metadata (
@Componentdecorator)
In modern Angular (15+), ALL new components should be standalone:
- βοΈ No NgModules
- βοΈ Cleaner structure
- βοΈ Faster builds
- βοΈ Better routing
- βοΈ Angular 20 best practice
Letβs create one!
π© 2. Creating Your First Standalone Component
Run:
ng generate component profile-card --standalone
Angular creates:
profile-card.component.tsprofile-card.component.htmlprofile-card.component.scss
By default, Angular does NOT auto-import your component into AppComponent.
(Standalone components = no module to declare them in!)
We will do that next.
π¨ 3. Understanding Component Anatomy
Open profile-card.component.ts.
You should see something like:
import { Component } from '@angular/core';
@Component({
selector: 'app-profile-card',
standalone: true,
templateUrl: './profile-card.component.html',
styleUrl: './profile-card.component.scss'
})
export class ProfileCardComponent {}
Breakdown:
| Section | Meaning |
|---|---|
selector | HTML tag to use the component |
standalone | Tells Angular this component has no module |
templateUrl | HTML file |
styleUrl | SCSS/CSS file |
Now letβs add content.
π« 4. Building the ProfileCard Component
Open: profile-card.component.html
Replace with:
<div class="card">
<img src="https://i.pravatar.cc/150?img=3" alt="Avatar" />
<h2>{{ name }}</h2>
<p>{{ role }}</p>
</div>
Now update the TS logic:
import { Component } from '@angular/core';
@Component({
selector: 'app-profile-card',
standalone: true,
templateUrl: './profile-card.component.html',
styleUrl: './profile-card.component.scss'
})
export class ProfileCardComponent {
name = 'Sarah Connor';
role = 'Angular Developer';
}
Add some simple CSS:
.card {
width: 220px;
padding: 16px;
border-radius: 10px;
background: #ffffff;
box-shadow: 0 4px 18px rgba(0, 0, 0, 0.1);
text-align: center;
}
img {
border-radius: 50%;
margin-bottom: 12px;
}
π¦ 5. Display the Component in AppComponent
Open: app.component.ts
Add the component to imports:
import { Component } from '@angular/core';
import { ProfileCardComponent } from './profile-card/profile-card.component';
@Component({
selector: 'app-root',
standalone: true,
imports: [ProfileCardComponent],
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {}
Now use the component in the template:
app.component.html:
<h1>Day 2: Components & Data Binding</h1>
<app-profile-card></app-profile-card>
Refresh β You should see a beautiful profile card βοΈ
π© 6. Data Binding (Core of Angular Templates)
Angular supports 4 primary data-binding types:
-
Interpolation (one-way: TS β HTML)
{{ username }} -
Property Binding
<img [src]="imageUrl" /> -
Event Binding
<button (click)="doSomething()">Click</button> -
Two-way Binding
<input [(ngModel)]="username" />
Letβs practice them all.
π₯ 7. Build a Counter Component (Signals Version)
Generate:
ng generate component counter --standalone
Replace content:
counter.component.ts
import { Component, signal } from '@angular/core';
@Component({
selector: 'app-counter',
standalone: true,
templateUrl: './counter.component.html'
})
export class CounterComponent {
count = signal(0);
increment() {
this.count.update(c => c + 1);
}
decrement() {
this.count.update(c => c - 1);
}
}
counter.component.html
<h3>Counter: {{ count() }}</h3>
<button (click)="decrement()">-</button>
<button (click)="increment()">+</button>
Now import the component:
app.component.ts:
imports: [ProfileCardComponent, CounterComponent]
Use it:
app.component.html:
<app-profile-card></app-profile-card>
<app-counter></app-counter>
Now you have two working components!
π¦ 8. Two-way Binding Demo (Inputs + Text)
Generate:
ng generate component message-editor --standalone
message-editor.component.ts
import { Component, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-message-editor',
standalone: true,
imports: [FormsModule],
templateUrl: './message-editor.component.html'
})
export class MessageEditorComponent {
message = signal('Hello Angular!');
}
message-editor.component.html
<input [(ngModel)]="message()" />
<p>You typed: {{ message() }}</p>
Import it and use it:
app.component.ts:
imports: [ProfileCardComponent, CounterComponent, MessageEditorComponent]
Template:
<app-message-editor></app-message-editor>
π© 9. Parent β Child Communication (Inputs)
Update ProfileCard to accept data:
profile-card.component.ts
import { Component, input } from '@angular/core';
@Component({
selector: 'app-profile-card',
standalone: true,
templateUrl: './profile-card.component.html',
styleUrl: './profile-card.component.scss'
})
export class ProfileCardComponent {
name = input<string>('Default User');
role = input<string>('Frontend Developer');
}
Use it:
<app-profile-card
[name]="'Luke Skywalker'"
[role]="'Jedi Master'"
></app-profile-card>
π« 10. Child β Parent Communication (Outputs)
Generate:
ng generate component emoji-picker --standalone
emoji-picker.component.ts
import { Component, output } from '@angular/core';
@Component({
selector: 'app-emoji-picker',
standalone: true,
templateUrl: './emoji-picker.component.html'
})
export class EmojiPickerComponent {
choose = output<string>();
sendEmoji(emoji: string) {
this.choose.emit(emoji);
}
}
emoji-picker.component.html
<button (click)="sendEmoji('π')">π</button>
<button (click)="sendEmoji('π€')">π€</button>
<button (click)="sendEmoji('π₯')">π₯</button>
Use it in AppComponent:
app.component.ts (logic)
selectedEmoji = signal('π');
updateEmoji(e: string) {
this.selectedEmoji.set(e);
}
app.component.html
<h2>Selected Emoji: {{ selectedEmoji() }}</h2>
<app-emoji-picker (choose)="updateEmoji($event)"></app-emoji-picker>
Boom βοΈ Real parent β child β parent communication.
π End of Day 2 β What You Learned
Today was big. You learned:
- βοΈ Creating standalone components
- βοΈ Component structure
- βοΈ Template syntax
- βοΈ Signals inside components
- βοΈ Property binding
- βοΈ Event binding
- βοΈ Two-way binding
- βοΈ Input & Output communication
- βοΈ Passing data between components
This is 80% of Angularβs foundation. Youβre doing amazing.
π§ͺ Day 2 Challenge
Build a component called:
π user-status
Features:
- Accept
usernameas input - Accept
online(boolean) as input - Show:
John Doe β Online π’ OR John Doe β Offline π΄
- Add a toggle button in
AppComponentto flip status - Use signals for state