If you’ve ever worked on a dynamic front-end, you know how tedious it can be to manually update the UI when data changes. Knockout.js simplifies this process using observables and a declarative binding syntax, keeping your HTML in sync with your JavaScript automatically.
Knockout follows the MVVM (Model-View-ViewModel) pattern, making it an alternative to traditional MVC-based frameworks. Here’s a quick breakdown:
- Model – The raw data (API responses, database values, etc.).
- View – The HTML structure with Knockout binding directives.
- ViewModel – The JavaScript logic that connects data to the UI.
If you’ve used AngularJS, you’ll find similarities—but without controllers or modules. Knockout.js is especially useful for real-time UI updates in single-page applications (SPAs) or dynamic form handling, all without the heavy overhead of modern frameworks like React or Vue.
Now, let’s dive into how it works with a quick example. 🚀
Our Example, Let's Begin!
Because really that's all we're here for. So for this example I'll try to cover as many basic Knockout elements as I can without it getting too confusing.
My data/model will be an object array filled with 'movie' objects, and I'll be displaying them onto my View, or web page, using a Knockout binding syntax that we'll get into down below.
I'll show the syncing capabilities of Knockout by adding new movies and by editing the current ones and showing them update in parallel in the View. I won't show deletions, but it's basically the same concept.
Any additions or deletions on your array will be reflected on your View automatically. So let's dive in.
Create A Model
In Knockout.js, the model represents your data. This can be anything from simple JavaScript variables to JSON data from an API.
For this guide, we’ll use a hardcoded JavaScript object as our model, but in real-world applications, data typically comes from a database, API, or user input.
Here’s how we define a simple Movie model:
// we can declare this outside of our ViewModel
function movie(name, year)
{
var self = this;
self.name = name;
self.year = year;
}
This is just a basic JavaScript object—nothing Knockout-specific yet. It acts as a template for storing movie data, which we’ll later bind to our UI using Knockout’s observables.
Next, let’s look at how to set up a ViewModel to handle data and UI interactions.
Creating a ViewModel in Knockout.js
The ViewModel in Knockout.js acts as the bridge between your data (model) and your UI (view). It’s where you define:
✅ Observable properties – Automatically notify the UI when data changes.
✅ Functions & logic – Handle UI interactions, like adding or removing items.
✅ Computed properties – Automatically update based on other observables.
What are Observables?
An observable is a special Knockout property that updates the UI whenever its value changes.
Let’s modify our Movie model from earlier by making name
an observable:
function Movie(name, year) {
this.name = ko.observable(name); // Observable property
this.year = year; // Regular property
}
Now, any UI element bound to name
will automatically update when its value changes.
Building the ViewModel
Next, let’s define our MoviesViewModel, which will store and manage a list of movies:
function MoviesViewModel() {
var self = this;
// Create movie instances
var movie1 = new Movie("The Matrix", "1999");
var movie2 = new Movie("The Matrix Reloaded", "2003");
var movie3 = new Movie("The Matrix Revolutions", "2003");
// Store movies in an observable array
self.movies = ko.observableArray([movie1, movie2, movie3]);
// Function to add a new movie
self.addMovie = function () {
self.movies.push(new Movie("New Movie", ""));
};
// Computed property: Automatically updates when movies are added/removed
self.movieCount = ko.computed(function () {
return self.movies().length;
}, self);
}
// Activate Knockout.js
ko.applyBindings(new MoviesViewModel());
Breaking It Down
✔ ko.observableArray([])
– Makes the movie list dynamic, automatically updating the UI when modified.
✔ self.addMovie
– Pushes a new movie into the array, which updates the UI in real-time.
✔ ko.computed()
– The movieCount
property automatically recalculates whenever the movies
array changes.
✔ ko.applyBindings(new MoviesViewModel())
– Activates Knockout.js, binding the ViewModel to the UI.
At this point, our data structure is ready—next, let’s build the View (HTML) to display our movies.
Creating a View in Knockout.js
The View in Knockout.js is your front-end HTML, enhanced with Knockout binding directives that keep it in sync with your ViewModel. These bindings automatically update the UI when your data changes, eliminating the need for manual DOM manipulation.
Knockout provides various data-bind directives, including:
- Binding variables to DOM elements (e.g., input fields, text content)
- Rendering lists and arrays dynamically
- Handling user interactions like button clicks
Here’s a simple view setup, broken down into key elements:
<div style="float:left;">
<table>
<tbody data-bind="foreach: movies">
<tr>
<td><input data-bind="value: name" /></td>
</tr>
</tbody>
</table>
</div>
Breaking It Down:
✔ data-bind="foreach: movies"
– Loops through the movies
array and repeats the <tr>
element for each item.
✔ data-bind="value: name"
– Binds the input field to the name
property of each movie, ensuring real-time updates.
Displaying Bound Data
To visually confirm that changes propagate throughout the UI, we display movie names separately:
<div style="float:left; margin-left: 10px;">
<table>
<tbody data-bind="foreach: movies">
<tr>
<td><div data-bind="text: name"></div></td>
</tr>
</tbody>
</table>
</div>
Here, instead of using an input field, we use data-bind="text: name"
to display movie names as text, showing how Knockout keeps everything in sync.
Adding Interactivity
<div style="clear:both;"></div>
<div data-bind="text: movieCount"></div>
<input type="button" value="Add Movie" data-bind="click: addMovie" />
✔ data-bind="text: movieCount"
– Binds the computed property that keeps track of the number of movies.
✔ data-bind="click: addMovie"
– Binds the button’s click event to addMovie
, allowing users to dynamically add movies.
Final Overview
With this setup, our Knockout.js app is now fully functional:
- Updating an input field instantly updates the corresponding text element.
- Clicking “Add Movie” dynamically adds new movies to the list.
- The computed property (
movieCount
) updates in real time to reflect the total number of movies.
This is the core power of Knockout.js—keeping your UI and data automatically in sync, reducing the need for boilerplate event handling.
That's just a quick glimpse at a very simple use case, but it's a big part of why Knockout.js can be beneficial to a website. Particularly to a very dynamic single page application or ajax heavy site.
There's tons and tons more that you can do with Knockout.js so feel free to play around with the library and to come up with cool ways to implement it into your websites. I hope this helps anyone who's brand new to Knockout and just wants to take it for a test drive to see if it's right for them. Happy Coding!
The Full Example For Your Copy/Paste Pleasure
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.5.0/knockout-min.js"></script>
</head>
<body>
<div style="float:left;">
<table>
<tbody data-bind="foreach: movies">
<tr>
<td><input data-bind="value: name" /></td>
</tr>
</tbody>
</table>
</div>
<div style="float:left; margin-left: 10px;">
<table>
<tbody data-bind="foreach: movies">
<tr>
<td><div data-bind="text: name"></div></td>
</tr>
</tbody>
</table>
</div>
<div style="clear:both;"></div>
<div data-bind="text: movieCount"></div>
<input type="button" value="Add Movie" data-bind="click: addMovie" />
<script>
function Movie(name, year) {
this.name = ko.observable(name);
this.year = year;
}
function MoviesViewModel() {
var self = this;
var movie1 = new Movie("The Matrix", "1999");
var movie2 = new Movie("The Matrix Reloaded", "2003");
var movie3 = new Movie("The Matrix Revolutions", "2003");
self.movies = ko.observableArray([movie1, movie2, movie3]);
self.addMovie = function () {
self.movies.push(new Movie("New Movie", ""));
};
self.movieCount = ko.computed(function () {
return self.movies().length;
}, self);
}
ko.applyBindings(new MoviesViewModel());
</script>
</body>
</html>