The Component Tree
Angular applications are built from components. Every component is responsible for one piece of the UI. Together, they form a tree — a hierarchy where components contain other components, all the way down from one root at the top.
Every Angular app is a tree
Section titled “Every Angular app is a tree”When bootstrapApplication runs, it renders the root component — App — into the <app-root> element in index.html. From there, App’s template can include other components, which can include others, and so on.
App (root)├── NavBar│ └── SearchForm├── RouterOutlet│ ├── Home│ │ └── MovieCard (×n)│ ├── Browse│ │ └── MovieCard (×n)│ ├── MovieDetail│ └── Watchlist│ └── MovieCard (×n)└── ToastThis is the CinemaVault component tree. Every box is a component — a TypeScript class with its own template, styles, and logic.
How components nest
Section titled “How components nest”A component includes another component by adding its selector to its template. Here is a simplified App template that includes a NavBar component:
<app-nav-bar /><main> <router-outlet /></main><app-toast />Angular sees <app-nav-bar /> and looks for a component whose selector is 'app-nav-bar'. It renders that component in place.
The <router-outlet /> is a special Angular component that renders whichever page component matches the current URL.
Parent and child
Section titled “Parent and child”When component A includes component B in its template, A is the parent and B is the child. This relationship determines how data flows:
- Data flows down: parents pass data to children via
@Input()properties - Events flow up: children emit events that parents listen to via
@Output()properties
In CinemaVault, Home passes individual Movie objects down to MovieCard. MovieCard emits an event when the user clicks the watchlist toggle button. Home listens for that event and calls the WatchlistService.
Why the tree model matters
Section titled “Why the tree model matters”The tree gives Angular a clear mental model for:
- Rendering: Angular renders from the root down. When data changes, it re-renders only the affected subtrees.
- Dependency injection: Services provided at the root are available to any component in the tree.
- Communication: Data flows down via inputs; events flow up via outputs. This predictable flow makes large apps understandable.
CinemaVault’s tree
Section titled “CinemaVault’s tree”Look at the CinemaVault repository and notice how the src/app/ directory maps to the tree:
src/app/├── app.ts ← root (App)├── components/│ ├── nav-bar/ ← NavBar (always visible)│ ├── movie-card/ ← MovieCard (used on 3 pages)│ └── toast/ ← Toast (always visible)└── pages/ ├── home/ ← Home (route: /) ├── browse/ ← Browse (route: /browse) ├── search-results/ ← SearchResults (route: /search) ├── movie-detail/ ← MovieDetail (route: /movies/:id) └── watchlist/ ← Watchlist (route: /watchlist)Shared components that appear on multiple pages live in components/. Page-level components that correspond to routes live in pages/.
Exercise
Section titled “Exercise”- On paper or in a drawing tool, sketch the component tree for a hypothetical blog app. It should have: a
Header, aPostList(on the main page), aPostCard(insidePostList), aSidebar, and a singlePostDetailpage. - Look at the CinemaVault source. Find the
app.htmlfile. Which components does it include directly? - In the tree diagram at the top of this lesson,
MovieCardappears three times (under Home, Browse, and Watchlist). Why is this fine?
- Every Angular app is a tree of components rooted at
App. - Components nest by including other components’ selectors in their templates.
<router-outlet>renders whichever page component matches the current URL.- Data flows down via
@Input(); events flow up via@Output(). - Shared components live in
components/; page components live inpages/by convention.