Components and Templates

Chapter 2
Components and Templates
Authoring a component's markup, scoping its styles, and composing several components into one page

Chapter 1's GreetingComponent used a separate template file. This chapter covers the rest of a component's anatomy — inline templates and styles as an alternative, how Angular keeps one component's CSS from leaking into another's, and nesting components together to build an actual page, the direct equivalent of composing JSX components in React (Fundamentals Chapter 9).

Inline Template and Styles

import { Component } from '@angular/core'; @Component({ selector: 'app-badge', standalone: true, template: `<span class="badge">New</span>`, styles: [`.badge { background: gold; padding: 2px 8px; border-radius: 8px; }`], }) export class BadgeComponent {}

template (a backtick string, allowing multiple lines) and styles (an array of strings) are direct alternatives to templateUrl/styleUrl — fine for a small enough component that separate files would be overkill. Larger components generally still use separate .html/.css files, which most editors syntax-highlight more usefully than a string embedded in TypeScript.

Style Encapsulation — Styles Don't Leak Between Components

// alert.component.ts @Component({ selector: 'app-alert', standalone: true, template: `<p class="box">Careful!</p>`, styles: [`.box { background: red; }`], }) export class AlertComponent {} // info.component.ts — a completely different .box, same class name @Component({ selector: 'app-info', standalone: true, template: `<p class="box">FYI</p>`, styles: [`.box { background: blue; }`], }) export class InfoComponent {}

Both components use a class called .box, with completely different styling — and both render correctly, with no collision. By default, Angular scopes each component's styles so they only ever apply to that component's own template, achieved by attaching unique generated attributes behind the scenes. This is functionally similar to what CSS Modules or styled-components give a React project deliberately — Angular does it automatically, with no extra setup, for every component.

Composing Components Together

// app.component.ts import { Component } from '@angular/core'; import { HeaderComponent } from './header/header.component'; import { FooterComponent } from './footer/footer.component'; @Component({ selector: 'app-root', standalone: true, imports: [HeaderComponent, FooterComponent], templateUrl: './app.component.html', }) export class AppComponent {}
<!-- app.component.html --> <app-header></app-header> <main> <h1>Main content</h1> </main> <app-footer></app-footer>

Every standalone component used inside another's template must be listed in that component's own imports array — the explicit step Chapter 1's third challenge already required. <app-header></app-header> and <app-footer></app-footer> in the template then place those components exactly where written, the same nesting idea as composing <Header /> and <Footer /> in a React JSX tree.

AppComponent ├── HeaderComponent // <app-header> ├── (main content, written directly in app.component.html) └── FooterComponent // <app-footer>
A forgotten import fails differently than in React
Forgetting to add a component to another's imports array doesn't throw a JavaScript import error — Angular's compiler instead reports that it doesn't recognize the unknown HTML tag (app-header isn't a known element), since as far as the template compiler is concerned, an unimported selector is indistinguishable from a typo or a real, unrecognized HTML element.

Coding Challenges

Challenge 1

Create a component using inline template and styles (no separate .html/.css files) rendering a styled "Beta" tag, and use it inside AppComponent.

📄 View solution
Challenge 2

Build three components (Header, Sidebar, Footer), each with simple static content, and compose all three inside AppComponent's template to form a basic page layout.

📄 View solution
Challenge 3

Build two sibling components, each using the same CSS class name internally but styled completely differently, and use both inside AppComponent — confirming both render with their own correct styling and neither affects the other.

📄 View solution

Chapter 2 Quick Reference

  • template / styles — inline alternatives to templateUrl/styleUrl, fine for small components
  • Angular scopes each component's styles automatically — identical class names in different components never collide
  • A component used in another's template must be listed in that component's imports array
  • A missing import shows as an "unrecognized element" error, not a JS import error
  • Composing components by nesting their selector tags is the same idea as nesting JSX components in React
  • Next chapter: data binding — property binding, event binding, and two-way binding with ngModel