Comments Application View

In notebook:
FrontEndMasters BackboneJS
Created at:
2016-02-16
Updated:
2016-04-20
Tags:
JavaScript jQuery libraries
More optional things you can do (to make your life easier)
  var CommentModel = ...

var CommentsCollection = Backbone.Collection.extend({...});

var commentTemplate = _.template('...');

var CommentView = Backbone.View.extend({...});

var CommentsApp = Backbone.View.extend({

  el: $('.comments'),

  initialize: function(){
    this.collection = new CommentsCollection();
    this.listenTo( this.collection, 'add', this.renderComment );
    this.listenTo( this.collection, 'remove', this.renderCommentCount );
  },

  renderComment: function(model){
    model.view = new CommentView({ model: model });
    this.$('#comment-list').prepend( model.view.render() );
    this.resetFormFields();
    this.renderCommentCount();
  },

  resetFormFields: function(){
    this.$('form textarea, form input[name="email"]').val(null);
  },

  renderCommentCount: function(){
    var length = this.collection.length;
    var count = length === 1 ? '1 Comment' : length + ' Comments';
    this.$('.comment-count').text( count );
  },

  events: {
    'submit form': 'createComment'
  },

  createComment: function(event){
    event.preventDefault();

    // Create a new Comment Model with the data in the form
    var comment = {
      content: this.$('form textarea').val(),
      email: this.$('form input[name="email"]').val(),
      created_at: +new Date()
    };
    // The `validate` option ensures that empty comments aren't added
    this.collection.add( comment, { validate: true });
  }

});

$(function(){
  window.comments = new CommentsApp();
});
This view will be responsible for the whole comments widget.
  1. ​el​ : we're telling Backbone: this element (that this view will be responsible for) already exists in the DOM, we get it via a jQuery selector. We're using a CSS class selector, because we know there's only one .commentselement on the page.
  2. ​initialize​ : it will create the collection. (new ​CommentsCollection​). Listen to some events. Add: when we add a new model element, Remove: we remove an element
  3. ​renderComment​ : some helper methods
  4. ​resetFormFields​ : when you successfully "saved" a comment (and displayed it on the page), clear the comment form text
  5. ​renderCommentCount​ : very very naive, not recommended way of just displaying in plain english the number of comments
  6. ​events​ : "event delegation for free" Delegating, bubbling of events that happen in the DOM (e.g. click events). Talks about capturing the form submit event. We could even be more specific and use ​events: {'form #my-comment-form': 'createComment'}​ and scope it a specific DOM element ID. Talks about jQuery stealing the ​this​ when getting a DOM element, and that in this case it would make it more difficult to work with. Backbone brings it (this) back
  7. ​createComment​ : it gets an (DOM) event object. we stop the browser sending the form (preventDefault). Any Backbone view element has already a DOM element tied to it, that's already scoped. So doing ​this.$('form textarea').val()​ will scope the DOM query to the views DOM element. Adds a timestamp. Later we will  use the moment.js library to work with dates. Some trivia: Brendan Eich had only two weeks to write JavaScript. So they quickly ported the Java date object with all of the bugs included. Not easy to use, kind of useless, buggy. Better to use library. Or better to coerce them to a UNIX timestamp by adding the +​+new Date()​. Then finally add the new model to the collection (​this.collection.add(...)​) and making sure it passes validation. You have to explicitly add validation, make sure the method exists(?).
Last line, is equivalent of using $(document).ready, it's a shorthand:
  $(function(){
  window.comments = new CommentsApp();
});
The set up can happen while the page is loading, but this last initialisation has to happen when the page is loaded.