Backbone 101: Deeper into Models

by kyllle

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-alpha1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.2.2/backbone-min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/3.0.3/normalize.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone-localstorage.js/1.1.16/backbone.localStorage-min.js"></script>
<h2 class="pg-heading">Deeper into Backbone Models</h2>

<h3>Using `parse` to reformat model data returned from server</h3>
<p>Some of the time our model data will be returned from the server in a different format. We can override the parse method to work the data into a shape that suits us.</p>
<pre>
    parse: function(response) {
        console.log('Original response', response);
                
        // 1) Remove the `movie` hash so our data is flat
        response = response.movie;
		
        // 2) Update our attribute keys to read a little nicer
        response.title = response.original_title;
        response.description = response.desc;
        
        console.log('Model including updated keys', response);
        
        // 3) Remove the unrequired renamed keys
        delete response.original_title;
        delete response.desc;
                
        return response;
    }
</pre>

<br>

<h3>Using `toJSON` to reformat model data for posting to server</h3>
<p>When it comes to sending back data similar to the format we recieved we then have to override the models toJSON method</p>    
<pre>
    toJSON: function() {
        console.log('Attributes attached to model', this, this.attributes);
        
        // 1) Cache the attributes available on the cloned model
        // We clone the model to avoid impacting the current model data.
        var attrs = _.clone(this.attributes);
        
        // 2) Revert our updated attribute keys...

CSS

@import url(http://fonts.googleapis.com/css?family=Roboto:300,400,500);

* {
  -webkit-font-smoothing: antialiased;
  box-sizing: border-box;
}

body {
    font-family: Roboto;
    padding: 16px;
    line-height: 1.5;
    font-weight: normal;
    color: #ccc;
    background: #292929;
    font-size: 18px;
}

h1, h2, h3 {
    font-weight: normal;
}

.pg-heading {
    margin-bottom: 0;
}

a {
    color: #95baf6;
    transition: opacity .3s;
}

a:hover {
    opacity: 0.75;
}

input {
    border: none;
    height: 40px;
    outline: none;
    padding: 0 8px;
}



input[type=submit] {
    padding: 0 16px;
    background: #2196F3;
    color: white;
    transition: background .3s;
}

input[type=submit]:hover {
    background: #1E88E5;
}

input[type=submit]:active {
    background: #1976D2;
}

input[type=text] {
    transition: border-color .3s;
    border: 1px solid white;    
}

input.error {
    border: 1px solid #F44336;
}

pre {
    display: block;
    padding: 9.5px;
    margin: 0 0 10px;
    font-size: 13px;
    line-height: 1.428571429;
    color: #333;
    word-break: break-all;
    word-wrap: break-word;
    background-color: #f5f5f5;
    border: 1px solid #ccc;
    border-radius: 4px;
}

JavaScript

console.clear();

// Set up contact model
var Movie = Backbone.Model.extend({
    
    localStorage: new Store('movie-methods'),
    
    defaults: {
        watchlist: false,
        rated: false
    },
    
    parse: function(response) {
        console.log('Original response', response);
                
        // 1) Remove the `movie` hash so our data is flat
        response = response.movie;
		
        // 2) Update our attribute keys to read a little nicer
        response.title = response.original_title;
        response.description = response.desc;
        
        console.log('Model including updated keys', response);
        
        // 3) Remove the unrequired renamed keys
        delete response.original_title;
        delete response.desc;
        
        // 4) And return our updated response
        return response;
    },
    
    // Return the data back to its original state for the server
    toJSON: function() {
        console.log('Attributes attached to model', this, this.attributes);
        
        // 1) Cache the attributes available on the cloned model
        // We clone the model to avoid impacting the current model data.
        var attrs = _.clone(this.attributes);
        
        // 2) Revert our updated attribute keys to originals
        attrs.original_title = attrs.title;
        attrs.desc = attrs.description;
        
        // 3) Remove the unrequired renamed keys
        delete attrs.title;
        delete attrs.description;
        
        // or if we just need to send specific attributes back just return a picked hash
        console.log(_.pick(attrs, ['id', 'original_title', 'watchlist']));
        
        // 4) And return our updated attrs
		return {'movie': attrs}; // check local storage and you should see the saved object
    }
});

// Create some instances
var movie = new Movie({
    'movie': {
        'id': 1,
        'original_title': 'Pulp Fiction',
        'desc': 'Lorem ipsum dolor sit amet, consectetur...