Suggest an editImprove this articleRefine the answer for “Data binding in Angular”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**Data binding in Angular** connects a component's TypeScript properties to the HTML template. Four types: interpolation `{{ }}` renders text, property binding `[prop]` sets DOM properties, event binding `(event)` calls methods on user actions, and two-way binding `[(ngModel)]` keeps a form input and a component property in sync. ```html <input [(ngModel)]="username"> <p>Hello, {{ username }}!</p> ``` **Key point:** one-way binding (component to template) is the default. Use `[(ngModel)]` only for form inputs.Shown above the full answer for quick recall.Answer (EN)Image**Data binding in Angular** automatically syncs a component's TypeScript properties with its HTML template. No manual DOM manipulation needed. ## Theory ### TL;DR - Think of it like a live scoreboard: the component pushes data to the template, and user actions send events back - Four types: interpolation `{{ }}`, property binding `[prop]`, event binding `(event)`, two-way `[(ngModel)]` - Default direction is one-way (component to template), which is predictable and easier to debug - Use `[(ngModel)]` only for form inputs, not as a general solution ### Quick example ```typescript @Component({ template: ` <p>{{ title }}</p> // interpolation: renders text <img [src]="imageUrl"> // property binding: sets DOM property <button (click)="onClick()">Go</button> // event binding: calls method on click <input [(ngModel)]="name"> // two-way: input and property stay in sync <p>You typed: {{ name }}</p> ` }) export class AppComponent { title = 'Hello'; imageUrl = 'https://example.com/logo.png'; name = ''; onClick() { console.log('Clicked!'); } } ``` The template reads directly from component properties. Change `title` in the class and the `<p>` updates on the next change detection cycle. ### The four binding types **Interpolation** `{{ expression }}` converts a value to a string and places it in the DOM. Good for text content, not the right tool for DOM properties. **Property binding** `[property]="value"` sets a DOM property directly, not an HTML attribute. That distinction matters: `[src]="imageUrl"` sets `img.src` (the DOM property). `src="{{ imageUrl }}"` sets the HTML attribute and relies on the browser to sync it. For plain strings both look the same, but `[disabled]="isLoading"` only works correctly as property binding. **Event binding** `(event)="handler($event)"` listens to DOM events and runs a component method. The `$event` object gives you the native event. No `addEventListener` in TypeScript, no inline JS in the template. **Two-way binding** `[(ngModel)]="prop"` is shorthand for `[ngModel]="prop" (ngModelChange)="prop = $event"`. The square brackets set the value, the parentheses listen for changes. Requires `FormsModule` imported in your module. ### When to use | Situation | Binding type | |---|---| | Display text or computed values | `{{ value }}` | | Set attributes, classes, disabled state | `[property]="value"` | | Handle clicks, input events, form submit | `(event)="method()"` | | Simple form inputs needing two-way sync | `[(ngModel)]="prop"` | For complex state, skip `[(ngModel)]` and use event binding with property binding separately. Data flows in one direction and stays easy to trace. ### How Angular runs this Angular's compiler (AOT) converts your template into change detection instructions at build time. Zone.js patches browser APIs like `addEventListener` and `setTimeout`. When an event fires, Angular walks the component tree and updates only the bindings that changed. With `OnPush` change detection, it skips components whose inputs haven't changed, which helps with large component trees. ### Common mistakes **Mistake 1: Interpolation instead of property binding** ```html <!-- Sets the HTML attribute, not the DOM property --> <img src="{{ imageUrl }}"> <!-- Sets img.src directly --> <img [src]="imageUrl"> ``` For dynamic values that are not plain strings, attribute-based interpolation breaks silently. Use property binding for DOM properties. **Mistake 2: Forgetting FormsModule** ``` Error: Can't bind to 'ngModel' since it isn't a known property of 'input'. ``` Add `FormsModule` to your `@NgModule` imports array. In standalone components, import it directly in the component decorator. **Mistake 3: Calling methods in templates** ```html <!-- Called on every change detection cycle --> <div>{{ getUserName() }}</div> <!-- Bind to a property instead --> <div>{{ userName }}</div> ``` This is probably the most common performance issue I see in Angular codebases. Angular runs change detection many times per second during fast user interactions. A method call in a template gets invoked every single cycle. **Mistake 4: Two-way binding on non-form elements** ```html <!-- ngModel only works on form controls --> <div [(ngModel)]="data">Content</div> ``` For custom elements, use the explicit pattern: `[value]="data" (input)="data = $event.target.value"`. ### Real-world usage - Angular Material buttons: `[disabled]="isLoading"` while a request is in flight - Login forms: `[(ngModel)]` on simple fields, `[formControl]` for reactive forms - Data tables: `(selectionChange)="onSelect($event)"` on selection components - Dynamic styling: `[class.active]="isSelected"`, `[style.color]="textColor"` ### Follow-up questions **Q:** What is the difference between `[src]` and `[attr.src]`? **A:** `[src]` sets the DOM property. `[attr.src]` sets the HTML attribute. Use property binding by default. Attribute binding is mainly useful for ARIA attributes like `[attr.aria-label]` that have no matching DOM property. **Q:** How does `[(ngModel)]` work internally? **A:** It expands to `[ngModel]="value" (ngModelChange)="value = $event"`. The `[]` part sets the property, the `()` part listens for changes. You can use this same pattern to build two-way binding into your own components. **Q:** Why does binding to a method hurt performance? **A:** Angular's change detection runs on every async event. Each template method call executes every cycle. Bind to a property instead and compute the value once in the component class. **Q:** Why avoid two-way binding in large apps? **A:** It creates bidirectional data flow that is hard to trace. The preferred pattern is unidirectional: data flows down via property binding, events bubble up via event binding. This is also how NgRx and other state managers work. ## Examples ### Basic: One-way display ```typescript @Component({ template: `<h2>{{ hero.name }} (ID: {{ hero.id }})</h2>` }) export class HeroComponent { hero = { id: 1, name: 'Windstorm' }; // Renders: Windstorm (ID: 1) } ``` Interpolation reads from the `hero` object on every change detection cycle. Update `hero.name` and the template reflects it automatically. ### Intermediate: Todo list using all four types ```typescript @Component({ template: ` <ul> <li *ngFor="let todo of todos" [class.completed]="todo.done" (click)="toggle(todo)"> {{ todo.text }} </li> </ul> <input [(ngModel)]="newTodo" (keyup.enter)="add()"> ` }) export class TodoComponent { todos = [{ text: 'Buy milk', done: false }]; newTodo = ''; add() { this.todos.push({ text: this.newTodo, done: false }); this.newTodo = ''; } toggle(todo: { text: string; done: boolean }) { todo.done = !todo.done; } } ``` All four types in one component. `{{ todo.text }}` renders text. `[class.completed]` toggles a CSS class based on a boolean. `(click)` handles the toggle action. `[(ngModel)]` keeps the input field in sync with `newTodo`. Add `FormsModule` to your module imports for `ngModel` to work.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.