ModelView

The simplest implementation is to render a single model; it's a very straightforward algorithm. Extract data from the model and use a template engine to make the actual render with the data; finally, attach the result in the DOM:

class MyView extends Backbone.View {
  constructor(options) {
    super(options);
    template: _.template($("#my-template").html());
  }
  
  render() {
       var data = this.model.toJSON();
    var renderedHtml = this.template(data);
    this.$el.html(renderedHtml);
    return this;
  }
}

In the following code we can identify five steps to rendering the view.

  1. Get the template:
    $("#my-template").html()
    
  2. Compile the template:
    _.template($("#my-template").html())
    
  3. Get data from the model:
    var data = this.model.toJSON()
    
  4. Render the template with model data:
    renderedHtml = this.template(data)
    
  5. Put the result on the DOM:
    this.$el.html(renderedHtml)
    

Note that we return this in the render() method; this is useful for chaining calls. These steps are common for all views that need to render a model, so we can extract that behavior in a new view type. This view will own the generic algorithm and let the specific parts open to extend:

class ModelView extends Backbone.View {
  render() {
    var data = this.serializeData();

    // Compile the template
    var renderedHtml = _.template(this.template, data);

    // Put the result in the DOM
    this.$el.html(renderedHtml);
    return this;
  }

  serializeData() {
    var data;

    // Serialize only if a model is present
    if (this.model) {
      data = this.model.toJSON();
    }

    return data;
  }
});

The model data now is done in a separated method, serializeData(), allowing us to implement a different way to provide data to the view; however, it implements a default behavior that is needed in most cases.

The template is now compiled in the process using the Underscore template engine, so that you have to provide the template text and let it make the rest. But this leaves the view highly coupled with a template engine; what if you need to use a different one such as Handlebars?

We can use the same strategy as before in the serializedData() method, and put this behavior in a separated method. All template engines need two things: template text and data. Template text can be obtained by a jQuery selector, a string variable, pre-compiled template, and so on. So we will leave this open to the final implementation:

  class ModelView extends Backbone.View {  
    // Compile template with underscore templates. This method
    // can be redefined to implemente another template engine
    // like Handlebars or Jade
    compileTemplate() {
      var $el = $(this.template);
      return _.template($el.html());
    }

    // ...
  }

And, as we did with serializedData(), a default behavior is implemented.

class ModelView extends Backbone.View {
  render() {
    // Get JSON representation of the model
    var data = this.serializeData();
    var renderedHtml;

    // If template is a function assume that is a compiled
    // template, if not assume that is a CSS selector where
    // the template is defined and is compatible with
    // underscore templates
    if (_.isFunction(this.template)) {
      renderedHtml = this.template(data);
    } else if (_.isString(this.template)) {
      var compiledTemplate = this.compileTemplate();
      renderedHtml = compiledTemplate(data);
    }

    this.$el.html(renderedHtml);
    return this;
  }

  // …
}

In this case, the template property can be either a function or a string. If a string is used, the default behavior will be to use the Underscore template engine. If a function is used, the function gives us the freedom to use any template engine.

If we want to render a model in a view, we can do something like this:

var contact = new Backbone.Model({
  name: 'John Doe',
  phone: '5555555'
});

var ContactView extends ModelView {
  constructor(options) {
    super(options);
    this.template = $('#contact-template').html();
  }
  
  // ... anything else like event handlers
}

var contactView = new ContactView({
  model: contact,
  el: 'body'
});
contactView.render();

You only need to specify the template and the model, and you're done!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.227.9