Change detection is Angular’s process for propagating component-state changes to the rendered UI. After state changes, Angular checks template bindings and updates the view when a binding’s value differs. A component can therefore render an initial value and reflect a later event-handler assignment without explicitly using RxJS or signals. section 10.3.1
A binding refreshed after a click
A component can bind `{{name}}`, initially render “John,” and assign “Alex” from a button click. Change detection checks that binding after the state change and refreshes the displayed value. The example isolates the framework work that otherwise makes property updates appear automatic. section 10.3.1
Traditional Angular change detection is closely connected to Zone.js. It runs when a component is created and repeatedly during its lifetime, commonly around asynchronous events, then invokes view refresh work to propagate detected changes. This makes it a central part of component lifecycle behavior, not merely a template feature. section 7.2.2 section 10.3
The established approach has practical costs in larger applications:
- Checks can require long, deep inspection of large objects, delaying the UI update that users ultimately need. section 10.3.2
- A function called from a template may run on every change-detection cycle because Angular must call it to determine whether its return value changed. section 10.3.2
- Zone.js adds download and execution overhead before the application can function, harming time to interactive. section 10.3.2
Signals modernize this model by bringing change detection to a more granular level rather than relying on top-down checks. They also affect timing: effects are integrated with Angular’s lifecycle and re-execute with change detection, whereas computed signals behave differently. Multiple synchronous writes can consequently yield an effect observing only the latest value. section 1.4.4 section 7.2.2
Testing signal-backed services
A service test that depends on computed signals or effects may need change detection before assertions observe updated values. Create an empty standalone stub component, inject the service through TestBed, call `fixture.detectChanges()`, then assert the signal state. This keeps tests synchronous while accommodating lifecycle-bound signal updates. section 8.3.5
@Component({
selector: 'app-some-component',
template: `
<p>{{name}}</p>
<button (click)="name = 'Alex'">Change name</button>
`,
standalone: true,
})
export class SomeComponent {
name = 'John';
}
Use this component to trace the full path from a click event, through the `name` state assignment and template-binding check, to the refreshed paragraph. section 10.3.1
Zoneless applications are the forward-looking direction for reducing Zone.js dependence, alongside deeper change-detection changes. Treat this area as experimental: the publicly adopted approach remains subject to modification before it becomes a stable replacement. Existing applications can adopt modern reactive tools incrementally while accounting for compatibility and testing behavior. section 10.0 section 10.3.2

