Model inputs are special inputs that support two-way data binding. This means that one component can send new values to another, allowing both components to share and update data seamlessly.
You can make a model input required or assign it an alias, just as you would with a standard input.
Use model inputs in components that need to update values based on user actions. For instance, custom form controls like date pickers or combo boxes should use model inputs for their main values.
1import { Component, EventEmitter, Input, model, Output, ModelSignal } from '@angular/core';2
3@Component({4 selector: 'app-child',5 standalone: true,6 templateUrl: './child.component.html',7 styleUrl: './child.component.css',8})9export class ChildComponent {10 @Input({ required: true }) selected!: boolean;11 @Output() selectedChange = new EventEmitter<boolean>();12 selected: ModelSignal<boolean> = model<boolean>;13 // selected = model.required<boolean>; -> Make the Model required14}Model inputs enable the component author to assign values to a property. Apart from this, model inputs function similarly to standard inputs: you can read the value by calling the signal function, even in reactive contexts like computed and effect.
When a component assigns a new value to a model input, Angular can propagate this value back to the component that originally bound the value to the input. This process is known as two-way binding, as it allows data to flow in both directions.
Model with Signals
You can bind a writable signal to a model input.
1import { Component, WritableSignal, signal } from '@angular/core';2import { ChildComponent } from './child/child.component';3
4@Component({5 selector: 'app-root',6 standalone: true,7 imports: [ChildComponent],8 template: `<div>9 <app-child [(selected)]="userSelected" />10 </div>`,11})12export class AppComponent {13 userSelected: WritableSignal<boolean> = signal(false);14}In the example above, the ChildComponent component updates its selected model input, which then updates the userSelected signal in AppComponent. This connection keeps the selected and userSelected values in sync. Notice that the connection uses the userSelected signal itself, not just its current value.
Model with plain properties
You can bind a writable signal to a model input.
1import { Component } from '@angular/core';2import { ChildComponent } from './child/child.component';3
4@Component({5 selector: 'app-root',6 standalone: true,7 imports: [ChildComponent],8 template: `<div>9 <app-child [(selected)]="userSelected" />10 </div>`,11})12export class AppComponent {13 userSelected: boolean = false;14}In the example above, the ChildComponent can update its selected model input, which then sends these updates to the userSelected property in AppComponent. This connection ensures that the values of selected and userSelected stay in sync.
Change events
When you declare a model input in a component or directive, Angular automatically creates a corresponding output event named by appending 'Change' to the model input’s name.
This change event is emitted whenever you update the model input by using its set or update methods.
1import { Component, WritableSignal, signal } from '@angular/core';2import { ChildComponent } from './child/child.component';3
4@Component({5 selector: 'app-root',6 standalone: true,7 imports: [ChildComponent],8 template: `<div>9 <app-child [(selected)]="userSelected" (selectedChange)="selectChanged($event)" />10 </div>`,11})12export class AppComponent {13 userSelected: WritableSignal<boolean> = signal(false);14
15 selectChanged(selected: boolean) {3 collapsed lines
16 console.log(selected);17 }18}Differences Between model() and input()
Both input() and model() are used to define signal-based inputs in Angular, but they have key differences:
-
model(): Defines both an input and an output. The output is named with “Change” appended to the input name, supporting two-way binding. Users can choose to use the input, the output, or both.ModelSignalis writable, meaning its value can be changed using set and update methods, and will emit changes to its output. -
input(): Defines a read-only inputInputSignalthat can only be changed via the template.InputSignaldoes not emit changes.
Additionally, model inputs do not support input transformations, unlike signal inputs.