Reputation: 11725
I have a view that has a tooltip
attribute. I want to set that attribute dynamically on initialize
or render
. However, when I set it, it appears on the next instantiation of that view instead of the current one:
var WorkoutSectionSlide = Parse.View.extend( {
tag : 'div',
className : 'sectionPreview',
attributes : {},
template : _.template(workoutSectionPreviewElement),
initialize : function() {
// this.setDetailsTooltip(); // doesn't work if run here either
},
setDetailsTooltip : function() {
// build details
...
// set tooltip
this.attributes['tooltip'] = details.join(', ');
},
render: function() {
this.setDetailsTooltip(); // applies to next WorkoutViewSlide
// build firstExercises images
var firstExercisesHTML = '';
for(key in this.model.workoutExerciseList.models) {
// stop after 3
if(key == 3)
break;
else
firstExercisesHTML += '<img src="' +
(this.model.workoutExerciseList.models[key].get("finalThumbnail") ?
this.model.workoutExerciseList.models[key].get("finalThumbnail").url : Exercise.SRC_NOIMAGE) + '" />';
}
// render the section slide
$(this.el).html(this.template({
workoutSection : this.model,
firstExercisesHTML : firstExercisesHTML,
WorkoutSection : WorkoutSection,
Exercise : Exercise
}));
return this;
}
});
Here is how I initialize the view:
// section preview
$('#sectionPreviews').append(
(new WorkoutSectionPreview({
model: that.workoutSections[that._renderWorkoutSectionIndex]
})).render().el
);
How can I dynamically set my attribute
(tooltip) on the current view, and why is it affecting the next view?
Thanks
Upvotes: 3
Views: 4477
Reputation: 1869
You can define attribute
property as a function that returns object as result. So you're able to set your attributes dynamically.
var MyView = Backbone.View.extend({
model: MyModel,
tagName: 'article',
className: 'someClass',
attributes: function(){
return {
id: 'model-'+this.model.id,
someAttr: Math.random()
}
}
})
I hope it hepls.
Upvotes: 7
Reputation: 434606
I think your problem is right here:
var WorkoutSectionSlide = Parse.View.extend( {
tag : 'div',
className : 'sectionPreview',
attributes : {} // <----------------- This doesn't do what you think it does
Everything that you put in the .extend({...})
ends up in WorkoutSectionSlide.prototype
, they aren't copied to the instances, they're shared by all instances through the prototype. The result in your case is that you have one attributes
object that is shared by all WorkoutSectionSlide
s.
Furthermore, the view's attributes
are only used while the the object is being constructed:
var View = Backbone.View = function(options) {
this.cid = _.uniqueId('view');
this._configure(options || {});
this._ensureElement();
this.initialize.apply(this, arguments);
this.delegateEvents();
};
The _ensureElement
call is the thing that uses attributes
and you'll notice that it comes before initialize
is called. That order combined with the prototype behavior is why your attribute shows up on the next instance of the view. The attributes
is really meant for static properties, your this.$el.attr('tooltip', ...)
solution is a good way to handle a dynamic attribute.
Upvotes: 5