Lesson 4 of 30
The @Component decorator is doing more than you think — selector, template, styles, and host bindings are four separate concerns bolted onto one class.
12 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
This topic is about judgment and practical tradeoffs more than a single right answer — a mock interview is the better way to test yourself on it.
Be interviewed on this →Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
A component in Angular is a plain TypeScript class with a @Component decorator sitting on top of it. The decorator is metadata — it tells Angular four mostly-independent things: what HTML tag name activates this component (selector), what markup it renders (template or templateUrl), what CSS scopes to it (styles or styleUrl), and how it should behave as an element in someone else's template (host). The class body itself just holds the component's state and logic — signals, methods, injected services. Understanding a component means being able to point at each of those four decorator concerns and say what it's actually for, instead of treating the decorator as one undifferentiated blob of config.
import { Component, ChangeDetectionStrategy, input } from '@angular/core';
@Component({
selector: 'app-card',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
class: 'card',
'[class.card--highlighted]': 'highlighted()',
'[attr.aria-selected]': 'highlighted()',
},
template: `
<h3>{{ title() }}</h3>
<p><ng-content /></p>
`,
styles: `
:host {
display: block;
border-radius: 0.5rem;
padding: 1rem;
}
.card--highlighted {
outline: 2px solid var(--accent);
}
`,
})
export class CardComponent {
title = input.required<string>();
highlighted = input(false);
}
Selector: app-card is the tag name — <app-card> — that activates this component wherever it's used. The app- prefix isn't required syntax, it's convention: a namespace so your components can't collide with a native HTML element or someone else's custom element.
Template: could just as easily be templateUrl: './card.component.html' pointing at a separate file — same result, purely a style preference for whether markup lives inline or split out. Same for styles vs styleUrl.
Host bindings: this is the part people skip past. host: {...} doesn't describe anything inside the template — it describes the component's own host element, <app-card> itself, as it sits in whatever template uses it. class: 'card' puts a static class on the host tag. '[class.card--highlighted]': 'highlighted()' is a property binding evaluated against the component instance, toggling a class based on the highlighted signal. This is the same mechanism @HostBinding/@HostListener decorators provide — you'll see that decorator-based form in older code, but the host object on the decorator itself is the current, more common way to write it, because it keeps all of a component's metadata in one place instead of scattered across decorated class members.
app-card (or an org-specific prefix like acme-card) exists specifically to avoid colliding with native elements or other libraries' custom elements. A selector of just card is legal but risky in a codebase that might ever adopt a component library.host bindings apply to the element the component sits on, not something inside the template. It's easy to assume host: { class: 'card' } and putting class="card" on the template's outermost <div> are equivalent — they're not. The host object affects <app-card> itself; anything inside the template is a separate element tree entirely.OnPush isn't automatic just because you're using signals. You still write changeDetection: ChangeDetectionStrategy.OnPush explicitly today. Signals make OnPush easy to use correctly (they notify Angular precisely when they change), but the strategy itself is still something you opt into per component, not a default that flips on its own.Compare this to a React component: the JSX return statement is the template, a CSS module or styled-components call is the styles, and the function/component name (plus how it's imported and rendered as <Card />) plays the role of the selector — but React has no direct equivalent to host bindings, because in React the outermost JSX element you return is the thing that receives props like className, not a separate metadata channel. Angular splits these into four decorator-level concerns instead of folding them into the render function; the signals-fundamentals lesson next moves from configuring a component to the reactive primitive that drives what actually re-renders inside one.