Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle undefined values in the JSON data with Backbone Marionette

I have the following setup:

    App.module('TestUsers.Views', function(TestUsersViews, App, Backbone, Marionette, $, _) {
    TestUsersViews.UsersItemView = Marionette.ItemView.extend({
        template: testUsersItemViewTmpl
        , tagName: 'tr'
        , templateHelpers: {
            handleUndefined: function(val) {
                return (_.isUndefined(val) ? '' : val);
            }
        }
    });

    TestUsersViews.UsersTable = Marionette.CompositeView.extend({
        template: testUsersTmpl
        , tagName: 'table'
        , className: 'h-center'
        , itemView: TestUsersViews.UsersItemView
        , itemViewContainer: 'tbody'
        , initialize: function() {
            this.listenTo(this.collection, 'reset', function() {
                this.appendHtml = function(collectionView, itemView, index) {
                    collectionView.$el.append(itemView.el);
                }
            });
        }
    });
});

The structure of the Collection returned is:

[ { "apiStandardProfileRequest": { "headers": { "_total": 1, "values": [ { "name": "x-li-auth-token", "value": "name:ksBx" } ] }, "url": "http://api.linkedin.com/v1/people/jGEI3X15sx" }, "firstName": "Eileen", "headline": "Managing Director of Delivery at Kforce Professional Staffing", "id": "jGEI3X15sx", "industry": "Staffing and Recruiting", "lastName": "Adams (LION)", "location": { "country": { "code": "us" }, "name": "Greater Boston Area" }, "pictureUrl": "http://m.c.lnkd.licdn.com/mpr/mprx/0_y_g-snorc6G3qFIa->bjSsz4yRb6un3EaOkWSszeCX3-yW5gmr5SOqvpuzEQPz6wGg8x2vtspSH8c", "siteStandardProfileRequest": { "url": "http://www.linkedin.com/profile/view?>id=3633999&authType=name&authToken=ksBx&trk=api*a249733*s257591*" } },... ]

My template to render the data is:

    <td id="<%= id %>"><img src="<%= pictureUrl %>" width="16"      height="16"/><%= firstName %> <%= lastName %></td>   
<td><%= headline %></td>
<td></td>
    <td><%= location.country.code %></td>
    <td><%= location.name %></td>
    <td><a href="<%= siteStandardProfileRequest.url %>">Full Profile</a></td>

However, some users do not have a 'pictureUrl' and I get an error of 'Uncaught ReferenceError: pictureUrl is not defined'. I am not sure what I am doing wrong that the undefined value is not handled. I am sure this is an easy fix and any help is appreciated.

like image 934
Kianosh Avatar asked Nov 24 '25 05:11

Kianosh


1 Answers

Short Answer - override serializeData in Marionette.ItemView

There are two options. Either check for type undefined in the templates or make sure the data always has the model attributes defined.

The first is cumbersome and adds a lot of clutter to the templates. For the second case one approach as mentioned in other answer is to use model defaults. But that puts another problem.

Model defaults are meant to provide values for attributes which can always have a meaningful value. an example attribute "isValid" can have a default value of true. but there's no meaningful default for "lastName". Setting model defaults for such values have the side effect of saving the defaults to the server, where as your only requirement was to put defaults for views/templates.

To avoid this, you can override serializeData in Marionette.ItemView to add defaults only for rendering.

Backbone.Marionette.ItemView.extend({
  serializeData: function(){
    return _.extend({}, 
      this.model.renderDefaults ? _.result(this.model, 'renderDefaults') : {}, 
      this.model.toJSON()
    );
  }
});

In models you can put your defaults for rendering like this

Backbone.Model.extend({
  renderDefaults : {
    pictureUrl : 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D'
  }
});

or

Backbone.Model.extend({
  renderDefaults : function(){
    return {
      pictureUrl : 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D'
    }
  }
});
like image 88
Mohit Avatar answered Nov 26 '25 11:11

Mohit