Skip to content

Lesson 3 — Component communication

Objective

Design reusable components with small typed APIs and explicit state ownership.

Prerequisites

Signals, template bindings, events, and stable collection identity at a working level.

Mental model

Data normally flows down through inputs and domain events flow up through outputs. The component owning a business decision changes source state. Projection supplies optional structure without transferring ownership.

Why it exists

Explicit contracts make components composable, testable, and resistant to invalid combinations. Domain events communicate intent better than leaking browser events.

Working model: parent passes input; child emits output.

Engineering reality: ownership follows the business invariant, not necessarily the visual tree. Two-way binding is input/output syntax and can hide that decision.

Minimal example

readonly value = input.required<number>();
readonly degrees = computed(() => `${clamp(this.value()) * 3.6}deg`);
readonly statusChange = output<TopicStatus>();

Real-world usage

Design-system controls, feature cards, tables, and forms need APIs that express valid states while leaving domain transitions with the correct owner.

Common mistakes

  • injecting a global store into every reusable child;
  • emitting raw click when consumers need statusChange;
  • exposing many coupled boolean inputs;
  • allowing visual and accessible values to diverge;
  • using model() where ownership is not genuinely shared editing.

Mini lab

Task: Extract an accessible ProgressRingComponent with required signal input and computed presentation. Create TopicCardComponent with typed topic input, status output, and optional projected actions. Keep store mutation in the feature parent.

Constraints: clamp 0–100, expose progressbar name/min/max/value, and do not inject the tracker store into reusable cards.

Expected result: visual and ARIA progress agree; a card event causes the parent to update source state.

Hint 1

Put presentation derivation in the child and business transitions in the owner.

Hint 2

Replace boolean combinations with semantic variants, projected content, or separate components.

Solution direction — last resort

Use required signal inputs, a computed clamped angle, and a typed domain output. Let TopicsComponent invoke the store.

Verification

Test values below 0, 42, and above 100 through the public API and accessible DOM. Propose a replacement for 14 visual boolean inputs and identify impossible combinations.

Mastery evidence: design a compact API, locate source-state ownership, and prove the child does not perform the domain transition.

Bloom challenge

  1. Understand: signal input versus mutable decorated field.
  2. Apply: emit a typed domain event.
  3. Analyze: identify ownership hidden by two-way binding.
  4. Evaluate: projection, template fragments, or separate variants.
  5. Create: design a reusable card contract that prevents invalid combinations.

Summary

Good component boundaries communicate values and intent while keeping invariants with an explicit owner.

Spaced review

In Lesson 4, classify child presentation as derived or source state. In Lesson 10, test this contract without private implementation assertions.

What comes next

Continue to signals and state.