Chapter 2: Components & Inputs

Components & Inputs — the part where your app starts feeling like real Lego blocks. We’ll go slow, with lots of examples, analogies, and code you can copy-paste right now.

Imagine you’re building a house:

  • The parent component is like the living room.
  • The child component is like a smart lamp.
  • You want to tell the lamp: “Hey, shine with brightness 70 and color blue” → that’s passing data from parent → child using inputs.

In modern Angular (v19–21 as of Jan 2026), we almost always use the new signal-based inputs with input() instead of the old @Input() decorator. Why? It’s simpler, more reactive, plays perfectly with signals/computed/effect, and Angular can optimize change detection better.

1. What are Component Inputs?

Inputs are the official way a parent component gives data to a child component.

  • Parent decides → child receives and uses (but cannot change the value directly — it’s read-only from child’s perspective).
  • Classic name: “props” in React world.
  • In Angular → traditionally @Input(), now input() function (recommended).

Key advantages of input():

  • Returns a signal → automatic reactivity
  • No need for ngOnChanges in 90% of cases
  • Better tree-shaking & bundle size
  • Required inputs give compile-time errors if forgotten
  • Built-in transforms (e.g. string → number)

2. Creating a Reusable Child Component with Inputs

Let’s build something practical: a UserCard component that shows a person’s name, age, and avatar — and we’ll make it reusable.

Step 1: Generate the component

Bash

(or just create files manually)

src/app/user-card/user-card.component.ts

TypeScript

Notice:

  • input.required<T>() → TypeScript + Angular will complain at build/dev time if you forget to pass it
  • input<T>(defaultValue) → optional, falls back to default
  • We call them with () because they’re signals: name() reads current value
  • computed() → auto-re-runs when any signal it reads changes

3. Using the Child in a Parent (Passing Data)

Now let’s use it in app.component.ts (or any parent).

src/app/app.component.ts

TypeScript

What happens here?

  • [name]=”…” → property binding — passes the value into the input
  • For static strings/numbers you can sometimes skip [ ] (Angular allows <app-user-card name=”Priya”>), but always use [ ] when the value is dynamic or from a variable
  • If you forget a required input → dev server shows red error in console + browser warning

4. Aliases, Transforms, and Required in Practice

Sometimes you want:

  • Different name in template vs code
  • Auto-convert types (string “true” → boolean)

Example upgrade:

TypeScript

Usage:

HTML

→ isActive() will be true (attribute presence = true)

5. Quick Rules of Thumb (like a teacher would pin on wall)

  • Use input.required<…>() when the value must exist (prevents undefined bugs)
  • Use input<…>(default) when it’s optional
  • Read inputs with () — this.name() not this.name
  • Derive everything possible with computed() — it’s free performance & clean code
  • Never mutate input values directly — treat them as read-only (immutability = happiness)
  • If child needs to “change” something → use outputs (next chapter)

6. Mini Practice Task (do this now!)

  1. Add a new optional input to UserCard: role = input<string>(‘Guest’);
  2. Show it in template: <p>Role: {{ role() || ‘Not specified’ }}</p>
  3. In AppComponent, create 3 different cards:
    • One with role=”Developer”
    • One without role
    • One with role from a variable
  4. Bonus: Add highlight = input(false, {transform: booleanAttribute}) and if true → add background: #fff9c4; to .card in styles

Run ng serve → play with it!

Got questions? Want to see outputs next (child → parent communication), or debug something in your code? Just tell me — we’re building this step by step like real pair programming. 🚀

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *