# Model-View-ViewModel (MVVM)

> Add a ViewModel between your Model and View that handles all the UI state — data binding wires them together so the View just reacts to changes.

- **Category**: Software Design
- **Subcategory**: architectural
- **Canonical URL**: https://designpattern.fyi/patterns/mvvm/

---

## Description
**Intent**: Remove all UI logic from the View so it becomes a pure, dumb display layer driven entirely by the ViewModel.

**Context**: You're working in a framework with rich data-binding (Angular, Vue, React, WPF). Your Views contain logic they shouldn't — conditional rendering, state management, formatting — making them hard to test and maintain.

**Solution**: Three components:
1. **Model** — pure data and domain logic, no UI awareness.
2. **ViewModel** — transforms Model data into View-ready format, exposes observable properties and commands, handles all UI state.
3. **View** — binds to ViewModel properties and commands, contains zero logic.

Data binding does the wiring — View updates when ViewModel changes, ViewModel commands respond to user actions.


## Use Cases
Use in frameworks that support two-way data binding — Angular, Vue, React (with state management), WPF, SwiftUI. Especially powerful when the same ViewModel needs to drive multiple View formats.



## Implementation Example

```javascript
// ViewModel with basic data binding simulation
class ViewModel {
  constructor(model) {
    this.model = model;
    this.bindings = [];
  }
  setUserName(name) {
    this.model.name = name;
    this.notifyBindings();
  }
  bind(element, prop) {
    this.bindings.push({ element, prop });
  }
  notifyBindings() {
    this.bindings.forEach(b => {
      b.element[b.prop] = this.model.name;
    });
  }
}

```



## Trade-offs


### Advantages

- ViewModels are pure JS/TS classes — unit testable with zero UI framework dependencies.

- Perfect designer-developer split: designers own the View, devs own the ViewModel.

- Same ViewModel can drive a web view, mobile view, or widget without changes.




### Considerations & Drawbacks

- Two-way binding bugs are painful to trace — change propagation can loop in unexpected ways.

- Total overkill for simple forms or static UIs with minimal state.







