Multiple binding styles (including two-way) - now with Signals
Angular templates wire views to state through four precise patterns. With Signals, state becomes
explicit and reactive: read a signal by calling it in the template, and update it with .set()
or
.update()
in code. This keeps UI and state locked together with minimal boilerplate. (angular.dev)
1) Interpolation - render values into text (one-way)
Use {{ ... }}
to project values. In templates, call signals (e.g. {{ name() }}
) to read them.
Interpolation is one-way: component → view. Avoid side effects in expressions. (DEV Community)

2) Property binding - set element / directive / component inputs
Use [prop]="expr"
to bind DOM properties or inputs. For classes, styles and attributes there are
special syntaxes. When the bound value is a signal, read it with signal()
in the template. (DEV Community)


3) Event binding - react to user and DOM events
Use (event)="handler($event)"
. Combine with key aliases like keyup.enter
. With Signals, update
state via .set()
/ .update()
for clear, side-effect-free logic. (DEV Community)


4) Two-way binding - “banana-in-a-box” [(...)]
Two-way binding composes property + event binding. In Angular v20 you can bind plain values
or writable signals. When you pass a writable signal to a two-way binding, Angular keeps the
signal and the control in sync automatically. (angular.dev)
a) Template-driven forms with NgModel
Import FormsModule
. You may bind either to a class field or directly to a writable signal.
(When using a signal, bind the signal reference-do not call it.) (angular.dev)

If you instead wrote [(ngModel)]="name()"
, you’d be passing the value, not the signal, which
breaks two-way semantics. Bind the signal itself. (Reddit)
b) Custom component two-way: classic [prop]
+ (propChange)
→ [(prop)]
You can still implement two-way with an @Input()
and a matching @Output()
named propChange
.
Works perfectly alongside Signals used inside the component. (angular.dev)


In the classic pattern, [(value)]="x"
expands to [value]="x"
and (valueChange)="x = $event"
.
If x
is a signal, you can pass score()
for the input and handle the output to call
score.set
($event)
. (See the signal-native alternative below.) (angular.dev)
c) Signal-native two-way for custom components: model inputs
Angular also offers model inputs via model()
, a signal-based, first-class two-way API. The
child declares a model()
; the parent binds with [(...)]
-no manual event needed. (angular.dev)


Why Signals matter here
- Signals are getter functions; templates must invoke them:
{{ total() }}
. Angular’s
extended diagnostics will warn if you forget to call a signal in interpolation. (angular.dev) - Two-way with
[(ngModel)]
can bind directly to a writable signal (bind the signal, not its
value). This is supported in today’s Angular. (angular.dev) - For component-to-component two-way, model inputs (
model()
) provide a clean, signal-first API
without wiring @Output()
manually. (angular.dev)
Version context
As of Angular v20 (current stable in 2025), Signals are a core reactive primitive; templates must
call them, two-way binding supports signals, and model inputs are the signal-native way to
author two-way component contracts. (Angular Blog)
References (key docs & guides):
Signals overview and usage; invoking signals in templates. (angular.dev)
Template binding syntax (property, event, two-way). (DEV Community)
Two-way binding guide (including signals) and NgModel usage. (angular.dev)
Model inputs for signal-native two-way binding. (angular.dev)
Angular v20 release context / schedule. (Angular Blog)