CP
Programmers Picnic
Angular Lessons by Champak Roy
Angular Components Lesson

Making Components in Angular: Level 0 to Infinity

Learn how to create, display, style, connect, test, and deploy Angular components: from your first generated component to reusable inputs, outputs, signals, model inputs, content projection, lifecycle hooks, dynamic rendering, and production structure.

Start Lesson
Speak tag: speak0

1. Introduction to Angular Components

A component is the basic visual building block of an Angular application. A complete Angular app is not usually one giant page. It is a tree of small components: header, footer, cards, lists, forms, pages, dashboards, and dialogs.

Simple meaning: A component is a reusable piece of screen with its own TypeScript logic, HTML template, and CSS style.
Angular App
├── Header Component
├── Home Page Component
│   ├── Course Card Component
│   └── Testimonial Component
└── Footer Component

Checkpoint: Verify before continuing

Complete all checks to continue.

Speak tag: speak1

2. Component Mental Model

Think of a component as a small machine. It receives data, displays data, reacts to events, and may send data back to another component.

Angular Component Input Data parent, route, service Component TypeScript HTML CSS Output View screen and events

Checkpoint

Complete all checks to continue.

Speak tag: speak2

3. Generate Your First Component

The safest way to create a component is through Angular CLI. The CLI creates the TypeScript, HTML, CSS, and test files in the correct structure.

Command

ng generate component components/course-card

Short Form

ng g c components/course-card

Expected Files

src/app/components/course-card/
├── course-card.ts
├── course-card.html
├── course-card.css
└── course-card.spec.ts
Your Angular CLI version may use slightly different filenames or class names. Always open the generated .ts file and use the exact exported class name.

Checkpoint

Complete all checks to continue.

Speak tag: speak3

4. Anatomy of a Component

A component is a TypeScript class decorated with @Component. The decorator tells Angular how to use that class as a visual component.

import { Component } from '@angular/core';

@Component({
  selector: 'app-course-card',
  templateUrl: './course-card.html',
  styleUrl: './course-card.css'
})
export class CourseCard {
  title = 'Angular Components';
  level = 'Beginner';
}
Part Meaning Example
selector Custom HTML tag for the component. <app-course-card>
templateUrl HTML file for the view. ./course-card.html
styleUrl CSS file for this component. ./course-card.css
export class TypeScript logic and data. CourseCard

Checkpoint

Complete all checks to continue.

Speak tag: speak4

5. Display a Component on the Page

To show a component, place its selector in another component's template. In standalone Angular, also import the child component in the parent component.

course-card.html

<article class="course-card">
  <h3>{{ title }}</h3>
  <p>Level: {{ level }}</p>
</article>

app.ts or parent component

import { Component } from '@angular/core';
import { CourseCard } from './components/course-card/course-card';

@Component({
  selector: 'app-root',
  imports: [CourseCard],
  templateUrl: './app.html',
  styleUrl: './app.css'
})
export class App {}

app.html

<h1>Angular Component Practice</h1>

<app-course-card></app-course-card>

Checkpoint

Complete all checks to continue.

Speak tag: speak5

6. Component Styling

Component CSS is normally scoped to that component. This helps avoid accidental style collisions.

course-card.css

.course-card {
  max-width: 360px;
  padding: 18px;
  border: 1px solid #fed7aa;
  border-radius: 18px;
  background: #fff7ed;
}

.course-card h3 {
  color: #92400e;
  margin-top: 0;
}
Keep page-wide rules in src/styles.css. Keep component-specific rules in the component CSS file.

Checkpoint

Complete all checks to continue.

Speak tag: speak6

7. Data and Methods Inside Components

Component properties hold data. Component methods respond to user actions.

course-card.ts

export class CourseCard {
  title = 'Angular Components';
  enrolled = false;

  enroll(): void {
    this.enrolled = true;
  }
}

course-card.html

<article class="course-card">
  <h3>{{ title }}</h3>

  @if (enrolled) {
    <p>You are enrolled.</p>
  } @else {
    <button (click)="enroll()">Enroll</button>
  }
</article>

Checkpoint

Complete all checks to continue.

Speak tag: speak7

8. Components with Signals

A signal is reactive state. When a signal changes, Angular can update the places where that signal is used.

course-card.ts

import { Component, signal } from '@angular/core';

@Component({
  selector: 'app-course-card',
  templateUrl: './course-card.html',
  styleUrl: './course-card.css'
})
export class CourseCard {
  likes = signal(0);

  like(): void {
    this.likes.update(value => value + 1);
  }
}

course-card.html

<p>Likes: {{ likes() }}</p>

<button (click)="like()">
  Like
</button>

Checkpoint

Complete all checks to continue.

Speak tag: speak8

9. Parent to Child Data with input()

A parent component can send data into a child component. Modern Angular supports the input() function for declaring component inputs.

course-card.ts

import { Component, input } from '@angular/core';

@Component({
  selector: 'app-course-card',
  templateUrl: './course-card.html',
  styleUrl: './course-card.css'
})
export class CourseCard {
  title = input.required<string>();
  level = input('Beginner');
}

course-card.html

<article class="course-card">
  <h3>{{ title() }}</h3>
  <p>Level: {{ level() }}</p>
</article>

parent template

<app-course-card
  title="Angular Components"
  level="Level 0 to Infinity">
</app-course-card>
Older Angular examples may use @Input(). Both styles exist, but input() is the modern signal-based approach.

Checkpoint

Complete all checks to continue.

Speak tag: speak9

10. Child to Parent Events with output()

A child component can send an event to its parent. Modern Angular uses the output() function for custom events.

course-card.ts

import { Component, input, output } from '@angular/core';

@Component({
  selector: 'app-course-card',
  templateUrl: './course-card.html',
  styleUrl: './course-card.css'
})
export class CourseCard {
  title = input.required<string>();
  selected = output<string>();

  selectCourse(): void {
    this.selected.emit(this.title());
  }
}

course-card.html

<button (click)="selectCourse()">
  Select Course
</button>

parent template

<app-course-card
  title="Angular Components"
  (selected)="onCourseSelected($event)">
</app-course-card>

parent TypeScript

message = '';

onCourseSelected(courseTitle: string): void {
  this.message = `Selected: ${courseTitle}`;
}

Checkpoint

Complete all checks to continue.

Speak tag: speak10

11. Two-way Component Binding with model()

A custom child component can support two-way binding using model(). This is useful for reusable controls like rating boxes, counters, filters, and toggles.

rating-box.ts

import { Component, model } from '@angular/core';

@Component({
  selector: 'app-rating-box',
  template: `
    <p>Rating: {{ rating() }}</p>
    <button (click)="increase()">+</button>
  `
})
export class RatingBox {
  rating = model(0);

  increase(): void {
    this.rating.update(value => value + 1);
  }
}

parent template

<app-rating-box [(rating)]="courseRating"></app-rating-box>

<p>Parent Rating: {{ courseRating }}</p>

Checkpoint

Complete all checks to continue.

Speak tag: speak11

12. Content Projection with ng-content

Content projection lets a parent put custom content inside a child component. This is useful for reusable cards, panels, modals, and layouts.

panel.html

<section class="panel">
  <header>
    <ng-content select="[panel-title]"></ng-content>
  </header>

  <div class="panel-body">
    <ng-content></ng-content>
  </div>
</section>

parent template

<app-panel>
  <h2 panel-title>Angular Course</h2>
  <p>This paragraph is projected into the panel body.</p>
</app-panel>

Checkpoint

Complete all checks to continue.

Speak tag: speak12

13. Component Lifecycle

A component has a lifecycle: Angular creates it, initializes inputs, checks changes, renders it, and finally destroys it when it is no longer needed.

Hook When it runs Common use
constructor When class is created. Basic setup, dependency injection.
ngOnInit After inputs are initialized. Load initial data.
ngOnChanges When inputs change. React to parent input changes.
ngOnDestroy Before component is destroyed. Cleanup subscriptions or timers.
afterNextRender After next full render. DOM-dependent work.

Example

import { Component, OnInit, OnDestroy } from '@angular/core';

@Component({
  selector: 'app-timer-box',
  template: '<p>Timer running</p>'
})
export class TimerBox implements OnInit, OnDestroy {
  private timerId = 0;

  ngOnInit(): void {
    this.timerId = window.setInterval(() => {
      console.log('tick');
    }, 1000);
  }

  ngOnDestroy(): void {
    window.clearInterval(this.timerId);
  }
}

Checkpoint

Complete all checks to continue.

Speak tag: speak13

14. Referencing Child Elements with viewChild()

Sometimes a component needs a reference to an element or child component in its own template. Angular supports view queries for this.

Example

import { Component, ElementRef, viewChild } from '@angular/core';

@Component({
  selector: 'app-focus-box',
  template: `
    <input #nameInput placeholder="Name">
    <button (click)="focusName()">Focus Input</button>
  `
})
export class FocusBox {
  nameInput = viewChild.required<ElementRef<HTMLInputElement>>('nameInput');

  focusName(): void {
    this.nameInput().nativeElement.focus();
  }
}
Do not use view queries for everything. Prefer data binding first. Use queries when you truly need a DOM or child component reference.

Checkpoint

Complete all checks to continue.

Speak tag: speak14

15. Page Components vs Reusable Components

A clean Angular app separates route-level page components from smaller reusable UI components.

Type Meaning Examples
Page component Connected to a route. Home, Courses, Contact, Dashboard.
Reusable component Used inside many pages. Header, Footer, CourseCard, RatingBox.
Smart component Loads or manages data. CoursesPage.
Presentational component Receives data and displays UI. CourseCard.

Recommended Structure

src/app/
├── pages/
│   ├── home/
│   └── courses/
├── components/
│   ├── header/
│   ├── footer/
│   └── course-card/
└── services/
    └── course.service.ts

Checkpoint

Complete all checks to continue.

Speak tag: speak15

16. Dynamic Component Rendering

Most components are used directly in templates. Advanced apps can render components dynamically. This is useful for dashboards, plugin-style UIs, modals, or switching between component types.

Using NgComponentOutlet

import { Component } from '@angular/core';
import { NgComponentOutlet } from '@angular/common';
import { AdminCard } from './admin-card/admin-card';
import { StudentCard } from './student-card/student-card';

@Component({
  selector: 'app-dynamic-demo',
  imports: [NgComponentOutlet],
  template: `
    <button (click)="useAdmin()">Admin</button>
    <button (click)="useStudent()">Student</button>

    <ng-container *ngComponentOutlet="selectedComponent"></ng-container>
  `
})
export class DynamicDemo {
  selectedComponent = StudentCard;

  useAdmin(): void {
    this.selectedComponent = AdminCard;
  }

  useStudent(): void {
    this.selectedComponent = StudentCard;
  }
}

Checkpoint

Complete all checks to continue.

Speak tag: speak16

17. Testing Components

Component tests verify that the component can be created and that important behavior works.

Basic Test Shape

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CourseCard } from './course-card';

describe('CourseCard', () => {
  let component: CourseCard;
  let fixture: ComponentFixture<CourseCard>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [CourseCard]
    }).compileComponents();

    fixture = TestBed.createComponent(CourseCard);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

Run Tests

ng test

Checkpoint

Complete all checks to continue.

Speak tag: speak17

18. Deployment Check for Components

After making components, build and deploy the full Angular app. Your custom domain is:

https://angular.learnwithchampak.live/

Build

npm run build:github

Deploy

npm run deploy:github
For your custom domain root, use --base-href=/, not --base-href=/repo-name/.

Checkpoint

Complete all checks to continue.

Speak tag: speak18

19. Common Component Mistakes

Mistake Problem Fix
Forgetting to import child component Selector is not recognized. Add child component to parent imports.
Using wrong selector Component does not appear. Copy selector from generated .ts file.
Wrong exported class name Import error. Use exact class name from generated file.
Too much logic in one component Hard to maintain. Split into smaller components and services.
Editing generated test imports blindly Tests fail. Make tests match standalone component imports.
Putting API logic in every component Repeated code. Move API calls to services.

Checkpoint

Complete all checks to continue.

Speak tag: speak19

20. Student Assignment

Build a small component-based Angular page for a course website.

Create Components

ng g c components/site-header
ng g c components/site-footer
ng g c components/course-card
ng g c components/rating-box
ng g c pages/components-practice

Requirements

1. Show SiteHeader at the top.
2. Show three CourseCard components.
3. Pass course title using input().
4. Send selected course back to parent using output().
5. Add RatingBox using model().
6. Use component CSS for card design.
7. Add one ng-content based reusable panel.
8. Build successfully.
9. Deploy to angular.learnwithchampak.live.

Final Test

ng serve

Open:

http://localhost:4200

Final Checkpoint

Complete all checks to finish.

Final learning: Angular components let you build a large app from small, reusable, testable UI pieces.
Speak tag: speak20

Final Summary

Question Answer
What is an Angular component? A reusable UI building block with TypeScript, HTML, and CSS.
Which command creates a component? ng generate component component-name
How do we show a child component? Use its selector in the parent template and import it in the parent component.
How does parent send data to child? Use input() or @Input().
How does child send events to parent? Use output() or @Output().
How can a custom child support two-way binding? Use model().
What supports projected content? <ng-content>
What is a good structure? Put pages in pages and reusable UI in components or shared/components.