KnockoutJS Flickr App Tutorial – Part I

To better understand how to implementation of KnockoutJS, I have created a tutorial which creates a Flickr application searching Flickr photos based on tag and displaying them. It also allows the user to view an enlarged version of the photo and add it to a favorites section. Here is Balsamiq mockup of the application:


In this example the Model will contains the information/data for the application. In this case we have two types of data, Photo and Favorite. The Photo model will have the following structure:

  Photo = function(id, owner, title, farmId, serverId, secret, ispublic, isfriend, isfamily) { = id;
    this.owner = owner;
    this.title = title;
    this.farmId = farmId;
    this.serverId = serverId;
    this.secret = secret;
    this.ispublic = ispublic;
    this.isfriend = isfriend;
    this.isfamily = isfamily;

The Favorite Model is simply a collection of Photo models:

  Favorites = function(Photo) {
    return this.Photo = Photo;


The ViewModel not contains the objects that will be used in the view but also the functions and interactions between the model and the view. The first step is to create observable objects. KnockoutJS has three types of observable objects:

  • Simple object
  • Function
  • Array Object

Here are some how the observables will be used in KnockoutJS:

// Simple object
var myViewModel = {
    personName: ko.observable('Bob'),
    personAge: ko.observable(123)

function AppViewModel() {
    this.firstName = ko.observable('Bob');
    this.lastName = ko.observable('Smith');
    this.fullName = ko.computed(function() {
        return this.firstName() + " " + this.lastName();
    }, this);

var myObservableArray = ko.observableArray();    // Initially an empty array
myObservableArray.push('Some value');            // Adds the value and notifies observers

Keep in mind that some browser do not support getters and setters so all ko.observable objects are functions In order retrieve a set value, one will have to use the following code:

myViewModel.personName(); //will display Bob

To change the value of a viewModel, you will implement in the following manner:

myViewModel.personName(); //will display Roy

In order to create the proper structure, the first step is the create the objects of the viewModel. Some of the time, these objects will mirror the model data that has been returned from the server. However there will be times where we will need to create an object reflecting not only the information displayed to the user but also to record the interactions with the user. In our application, we have created a photos object which contains arrays of ‘image’ objects. The ‘image’ object has the following structure:

  • Photo object: this is an instance of the Photo object created in model
  • Photo src: this is the source for our image to be retrieved from Flickr
  photoViewModel = {
    //Photos: will be an array of image objects which will contain
    //Photo object and photo src
    photos: ko.observableArray([]),
    favorites: ko.observableArray([])

As you can see, the ‘photos’ and ‘favorites’ objects are initialized as empty knockout observable arrays. This is all that is needed in order to initially render the page. Once the user searches for a certain tag i.e. cat, dog, table, etc.., we will fire off a request to Flickr to retrieve the images. In the viewModel, we also create functions

photoViewModel = {
 ... //Photos and Favorites object are here //Function that will retrieve all the photos based on the search tag
 //and place them in the photos viewmodel
 getPhotos: function(formElement) {
   var searchTag, that;
   //reseting the previous search results[]);
   //getting the search tag
   searchTag = $(formElement).find('#search').val();
   that = this;
   $.getJSON(flickrURL + searchTag)
   .done(function(photoData) {
     return _.each(, function(photo) {
       var image;
       image = {
         photoObj: new Photo(,
         photoSrc: that.createSrc(,

We also need a function that will create the src URL for the images for us.

//Function that will create a src URL to be retrieved from Flickr</pre>
createSrc: function(farmId, serverId, id, secret, size) { return 'http://farm' + farmId + '' + serverId + '/' + id + '_' + secret + (size === "thumbnail" ? "_s.jpg" : "_n.jpg"); } 

To add a photo to the favorites, we simply take the photo object that the user has selected and add it to the favorites array. By simply adding the object to the array combined with the fact that the favorites object is bound to the DOM element on the view, the photo will appear in the designated area.

 //Function that will add the selected photo to the favorites viewmodel
 addToFavorites: function(id) {
   var currentPhotoObj, favoriteExists;
   //getting the photo object of the selected photo
   currentPhotoObj = _.find(, function(photo) {
     return photo.photoObj['id'] === id;
   //Checking to see if the item exists in the favorites or not
   favoriteExists = _.find(photoViewModel.favorites(), function(favorite) {
     return favorite.photoObj['id'] ===;
   //adding the photo object to the favorites list
   if (!favoriteExists) {

The remaining code will perform the following functions:

  • remove from favorites
  • Show larger image
//Function that will remove the selected photo from the favorites viewmodel
 removeFromFavorites: function(id) {
   return photoViewModel.favorites.splice(_.indexOf(photoViewModel.favorites(),
                _.find(photoViewModel.favorites(), function(favorite) {
                  return favorite.photoObj['id'] === id;
                })), 1);
 //Function that will show the larger image in the a modal box
 showLargerImage: function(id) {
   var currentPhotoObj, imageSrc;
   currentPhotoObj = _.find(, function(photo) {
     return photo.photoObj['id'] === id;
   imageSrc = photoViewModel.createSrc(currentPhotoObj.photoObj.farmId,
     height: 'auto',
     width: 'auto',
     loaderImgSrc: 'img/loader.gif',
     showSpinner: false
     return $('body').modal('updateContent', $('</pre>
<img alt="" />').attr('src', imageSrc)); } }; 

Note that in this process, we are using underscore.js and jquery.modal.js (a jquery plugin that I wrote myself).


The view being the center where we display the model at its current state to the user and also give the user the ability to modify/update the model. This is the markup for the search box:

<h1>Photo Finder</h1>
<strong>Search for photos in Flicker using tags</strong><form data-bind="submit: getPhotos">
 <input id="search" type="text" />

As you can see, we have bound the submit button to the ‘getPhotos’ function in our view model. This binding (for the submit button binding ensure that the button is in a form) will prevent the default submit action but also will allow you to use the form as a handler for the view model and perform the specific function needed. In our case, we use it to retrieve the Flickr photos and place them in our view model. Once the photos are retrieved, we add them to the photos object in the view model. Because the view model is bound to the DOM, therefore consumed by the ‘photos-template’. At this point, any changes made to the photos object in the view model will be reflected in the UI automagically.

<div id="main">
<h4>Search Results</h4>

<hr width="81%" />

<div id="results" data-bind="template: 'photos-template'"></div>
...<script id="photos-template" type="text/html">// <![CDATA[
<ul class="clearfix">
 {{each photos}}
<div class="imgResult"><img src="${photoSrc}" id="${}" alt="${photoObj.title}-    ${photoObj.owner}" title="${photoObj.title}" /></div>
<div class="tabs"><img src="img/fav-icon-sketch.png" width="40%" alt="add to favorites" data-bind="click: function() { addToFavorites( }"/>
          <img src="img/enlarge-sketch.png" width="40%" alt="show larger image" data-bind="click: function() { showLargerImage( }"/></div></li>
// ]]></script>

Also please notice that we have not only bound the photos object to this markup/template but we have also bound a couple of ‘click’ events that will call the appropriate function, passing the the photo id. Similar treatment for the favorites section:

<div id="favs">
<div class="header">Favorites<img src="img/fav-icon-sketch.png" alt="add to favorites" width="15%" /></div>
<div id="favorites" data-bind="template: 'favorites-template'"></div>
<h3>...<script id="favorites-template" type="text/html">// <![CDATA[
<ul class="clearfix">
 {{each favorites}}
<div class="imgResult"><img src="${photoSrc}" id="${}" alt="${photoObj.title}-${photoObj.owner}" title="${photoObj.title}" /></div>
<div class="tabs"><img src="img/remove-sketch.png" width="40%" alt="add to favorites" data-bind="click: function() { removeFromFavorites( }"/></div></li>
// ]]></script>


Next Steps

Common complaint of KnockoutJS is the what seems like the mixing of javascript, data-bind attributes, and markup. However KnockoutJS allows you to create custom bindings. One option to combat the overly tied application logic to the view is to create a custom binding similar to CSS classes. Ryan Niemeyer has suggested this procedure. In part II of this tutorial, we will tackle this option.