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.
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'
}
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With