Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Backbone.js - proper model initialization

Tags:

backbone.js

Questions: What is the proper way to initialize a backbone.js model when there are attributes that need to be stored in specific ways? Do i need to map the attributes that don't need any special formatting? I thought backbone.js did some kind of auto-mapping.

Example:

var MyModel = Backbone.Model.extend({

    initialize: function (options) {

        // These attributes need to be stored in a different format
        // Dates
        this.startYear = new Date(options.startTime).getFullYear();
        // Rounding numbers
        this.wholeNumber = Math.Round(options.numberWithDecimals);
        // Storing empty strings as nulls
        if (options.fullName == null || options.fullName == "") {
            this.fullName == null;
        } else {
            this.fullName = options.fullName;
        }

        // These are fine as they are
        this.fieldA = options.fieldA;
        this.fieldB = options.fieldB;
        this.fieldC = options.fieldC;
    },
});
like image 579
JT703 Avatar asked Sep 05 '12 16:09

JT703


People also ask

How do I set up backbone JS?

Downloading the UI library from its official website Development Version − Right click on this button and save as and you get the full source JavaScript library. Production Version − Right click on this button and save as and you get the Backbone-min. js library file which is packed and gzipped.

Is Backbone JS still used?

Backbone. Backbone has been around for a long time, but it's still under steady and regular development. It's a good choice if you want a flexible JavaScript framework with a simple model for representing data and getting it into views.

What is backbone JS model?

It is also known as the heart of the JavaScript application. Model contains dynamic data and its logic. It performs various types of action on the data like validation, conversion, computed properties, access control etc. 1.

Is Backbone JS frontend or backend?

Backend Synchronization BackboneJS is use with the front-end and back-end systems, allows the synchronization with the backend to provide support to RESTful APIs.


2 Answers

First you have to differentiate between attributes and instance variables.

Attributes: IMHO, it should be plain objects as String or Integer. They travel around the client and the server through the REST API. They are manipulated through the Model.get()/Model.set() methods. They are sent to the server through the Model.toJSON() (also they use to be sent to the template using the same .toJSON() method. If they change in some way then Backbone events are triggered. You can customize the initialization of this attributes manipulating the server side JSON information before it is sent to the Model overriding the Model.parse() method as @muistooshort has suggested.

Instance Variables: (the this.myAttribute thing) They can be complex objects. The don't trigger any implicit event in their change and they are not sent to the server in the save and update calls, and, in an standard way, they are not sent to the template.

In your example you're not storing any complex object and if you are not affraid that your model is gonna send more attributes to the server than it receives from the server you can go for the @muistooshort suggestion:

// code no tested
var MyModel = Backbone.Model.extend({
  parse: function(resp, xhr) {
    resp.startYear = new Date( resp.startTime ).getFullYear();
    resp.wholeNumber = Math.Round( resp.numberWithDecimals );
    if( resp.fullName == "" ) resp.fullName == null;

    return resp;
  },
});

Just remember you these are attributes and you have to access them in this way my_model.get( "startYear" )

The only problem with this solution is the derived attributes won't be updated if the original attribute changes. So you can come with another implementation:

// code no tested
var MyModel = Backbone.Model.extend({
  initialize: function(){
    this.updateAttributes();
    this.on( "change", this.updateAttributes, this );
  },

  updateAttributes: function() {
    this.set( "startYear", new Date( this.get( "startTime" ) ).getFullYear() );
    this.set( "wholeNumber", Math.Round( this.get( "numberWithDecimals" ) ) );
    if( this.get( "fullName" ) == "" ) this.set( "fullName", null );
  },
});

Updated

As @TomTu has suggested if your onlive attributes are only needed to feed the templates then a decorator is the best solution: https://stackoverflow.com/a/9687672/316700

like image 51
fguillen Avatar answered Oct 31 '22 05:10

fguillen


If all you need is helper values to be used in the templates you can compute them in the overwritten toJSON method that will add all the extra attributes that you might need when representing a model in a view.

As the documentation for Backbone.js says:

model.toJSON()

Return a copy of the model attributes for JSON stringification. This can be used for persistence, serialization, or for augmentation before being handed off to a view. ...

as I mentioned in a comment for another answer - altering the model in the parse method will result with creation of overhead which will be sent to the server every time model is saved and should be considered a sloppy and bad practice

Since the model initialization doesn't bind the options to the instance of the model in similar fashion as it does for the views you can always do that in the initialization method and then refer to the options from the overwritten toJSON method as required by whatever you want to achieve

like image 38
Tom Tu Avatar answered Oct 31 '22 06:10

Tom Tu