Tag Archives: backbone

How to do toggle functions in Backbone.js the right way

Recently a co-worker was asking me how best to implement a piece of toggle functionality in to a Backbone.js view. He was trying to replicate the usual jQuery toggle pattern within his backbone app but was getting confused and having some troubles accessing it from other views. This confusion comes from the fact that backbone suggests you create all of the view’s events using the events hash.

I’m writing this blog post because I actually had the exact same issue when I first started working with backbone so I feel it is a common issue and hopefully if you are reading this post I can shed some light on the subject for you.

Toggle functionality can be common in UI designs and usually is used to implement some kind of ability to turn something on and off or to disable then enable a piece of the UI.

There is an answer for this question on StackOverflow but personally I don’t really like the answer and would like to show you a more usable and dynamic way of creating some toggle functionality within your backbone views.

I prefer my approach below because I can easily allow other views access to my methods via a global events dispatcher or simply check the state of the object from another view and maybe display a message to the user within another view.

The ability to turn toggle functionality on and off in different places is really neat. This can easily crop up for instance when a client wants to move the button from one place to another and you find your self struggling with the move. Because we have the toggle state included as a property of the object we can easily check the current state of an element if need be, it will allow for much more complex use cases.

var View = Backbone.View.extend({
  events: {
    'click': 'toggleContent'
  },
  showmeState: true,
  toggleContent: function(){
    if (this.showmeState === false) {
      this.showText();
    } else {
      this.hideText();
    }
  },
  hideText: function() {
    this.$el.find('p').hide();
    this.showmeState = false;
  },
  showText: function() {
    this.$el.find('p').show();
    this.showmeState = true;
  }
});

Another use case for the above code would be for an Auto Sorting and Render of a collection in a live data environment.

var View = Backbone.View.extend({
  autoSortTimer: "",
  events: {
    'click': 'autoSort'
  },
  autoSorting: false,
  autoSort: function() {
    if(!this.autoSorting) {
      this.startAutoSort();
    } else {
      this.stopAutoSort();
    }
  },
  startAutoSort: function() {
    this.autoSorting = true;
    this.autoSortTimer = setInterval(function() {
      Dispatcher.trigger('resort');
    }, 1000);
    this.$el.find('#auto-sort-label').html('Auto Sort Columns - On');
  },
  stopAutoSort: function() {
    this.autoSorting = false;
    var autoSortTimer = this.autoSortTimer;
    clearInterval(autoSortTimer);
    this.autoSortTimer = "";
    this.$el.find('#auto-sort-label').html('Auto Sort Columns - Off');
  }
});

Backbone.js and Require.js Boilerplate

It’s painstakingly slow to start projects in Backbone using Require. I have created a simple boilerplate to save me some time when I need to start a new Backbone project.

The app contains a single model, a single collection and a single view. It also has support for the Require.js text library for ajaxing templates into the app.

The current folder structure is as follows:

├── css
│   └── base.css
├── js
│   ├── app
│   │   ├── tmpl
│   │   │   └── template.html
│   │   ├── collection.js
│   │   ├── model.js
│   │   └── view.js
│   ├── libs
│   │   ├── backbone-min.js
│   │   ├── jquery-2.0.3.min.js
│   │   ├── text.js
│   │   └── underscore-min.js
│   ├── main.js
│   └── require.js
└── index.html

It’s a bare bones approach and it’s hosted on GitHub, feel free to download it and maybe even contribute to it.

A Simple Backbone WordPress Example

I’ve been working on this blog now for a little under two weeks and I’ve started to build out the front end using Backbone.

WordPress JSON API

The first thing I needed was the blog content being returned via JSON so my backbone app could easily consume the data.

Plugins to the rescue, turns out some one has already done a pretty good job at creating a WordPress JSON API, I installed it and it seems to work perfectly.

Creating the backbone Front End

I’ve tried to keep this example as simple as possible. We use a model, a collection and two views.

The model is super simple:

var PostItem = Backbone.Model.extend({});

The collection contains a single API end point and a function to iterate over the data so we can push that data into the models.

var PostList = Backbone.Collection.extend({
 
  model: PostItem,
 
  url: 'http://blog.michaelfasani.com/api/get_posts/',
 
  parse: function (data) {
    var parsedData = [];
 
    //This is all the post data returned by the API call above.
    $(data.posts).each(function () {
      var id = this.id,
          type = this.type,
          slug = this.slug,
          url = this.url,
          status = this.status,
          title = this.title,
          title_plain = this.title_plain,
          content = this.content,
          excerpt = this.excerpt,
          date = this.date,
          modified = this.modified,
          categories = this.categories,
          tags = this.tags,
          author = this.author,
          comments = this.comments,
          attachments = this.attachments,
          comment_count = this.comment_count,
          comment_status = this.comment_status,
          custom_fields = this.custom_fields;
 
      parsedData.push({
        id: id,
        type: type,
        slug: slug,
        url: url,
        status: status,
        title: title,
        title_plain: title_plain,
        content: content,
        excerpt: excerpt,
        date: date,
        modified: modified,
        categories: categories,
        tags: tags,
        author: author,
        comments: comments,
        attachments: attachments,
        comment_count: comment_count,
        comment_status: comment_status,
        custom_fields: custom_fields
      });
    });
 
    return parsedData;
  }
 
});

Our first view is a view to display a single model:

var PostSingleView = Backbone.View.extend({
 
  tagName: 'li',
  
  className: 'single-post',
 
  template: _.template($('#single-post').html()),
 
  render: function() {
    this.$el.html(this.template(this.model));
    return this;
  }
});

Our second view is a list view which will display all of the single model views:

var PostListView = Backbone.View.extend({
 
  el: '#post-list',
	
  initialize: function() {
    this.listenTo(this.collection, 'sync', this.render);
    this.collection.fetch();
  },
 
  render: function() {
    this.$el.html('');
    this.collection.each(this.addSinglePost, this);
    return this;
  },
 
  addSinglePost: function(singlePost) {
    var view = new PostSingleView({
      model: singlePost.attributes
    });
  this.$el.append(view.render().el);
  }
});

I have put together a simple CSS style sheet and sample HTML page which contains my underscore templates and some containers for my views to work with.

All of this code can be downloaded and viewed via a GitHub Gist.