4

I have a backbone view like so

 window.InputView = Backbone.View.extend({
        tagName:'input',
        className:'',
        attributes:{},
        initialize:function(){
            this.attributes=this.model.attributes;
            this.el = this.make(this.tagName,this.attributes,'');
        }
    });

The problem I am having is that When I modify the attributes hash of the View it does not reflect on the el,

So I have to do something like this this.el = this.make(this.tagName,this.attributes,''); for the changes to reflect .

Is this the only way , or is there a better way to do it ? like automate it ?

Gautam
  • 7,868
  • 12
  • 64
  • 105

2 Answers2

1

You are simply overwriting the view's el property, which is not what you want, I think. As you see below, the make function does not attach the freshly created element to the DOM, so it won't appear, AND the old element is not removed from the page.

A possible way to fix it:

initialize: function(){
  this.attributes = this.model.attributes; // why are you doing this anyway? :)
  var $oldEl = this.$el; // backbone 0.91
  var newEl = this.make(this.tagName,this.attributes,'');
  $oldEl.after( newEl ); // the old element must be in the DOM, when doing this!
  $oldEl.remove();
  this.setElement( newEl ); // proper setup
}

Quotes from BackBone's source:

make: function(tagName, attributes, content) {
  var el = document.createElement(tagName);
  if (attributes) $(el).attr(attributes);
  if (content) $(el).html(content);
  return el;
},

setElement: function(element, delegate) {
  this.$el = $(element);
  this.el = this.$el[0];
  if (delegate !== false) this.delegateEvents();
  return this;
},
biziclop
  • 14,466
  • 3
  • 49
  • 65
  • I am doing `this.attributes = this.model.attributes;` because the model contains exactly the same attributes as the view's `el`. By the way I was looking for automatically updating the attributes of `el` when `view.attributes` changes . But thanks anyway, you have given me an Idea ! – Gautam Mar 04 '12 at 13:23
  • thanks biziclop. i was googling for a different problem, and this page came up. even though your answer didn't answer Gautman K's question, it helped me figure out an issue i was having. i'll add my comment to this incase anyone else has the same problem. in my app,i have nested views, and in the parent view, i would create the sub view, and attach the subview's subview.el property to the parent, then call render on the subview after. as for my subview, i also set the .attributes property in the initialize method of the subview. (continue..) – Khon Lieu Aug 16 '12 at 03:43
  • (continued..) but when i did that, the attributes didn't show up on the generated subview. turns out i had to put the attributes field in the view constructor e.g. new SubView({model: myModel, attributes:{att1:value}}). after doing that the html came out correct. looks like the el element is generated before the initialize method so it's never updated with the attributes if it's set in the initialize method. hope this helps someone out there. – Khon Lieu Aug 16 '12 at 03:48
1

To automate whatever you're trying to do when your model changes you need to bind a method to the change event of the model. In your initialize method you'd need something like:

initialize: function() {
    this.model.on("change", updateElement);
    ...
}

and then define that method later on in your view:

updateElement: function() {
    //use this.model.attributes to update your el
}

Now, anytime the model associated to that view changes the updateElement method will run.

ryanmarc
  • 1,670
  • 1
  • 10
  • 9
  • 1
    Rather than using `this.model.on("change"...` it's better practice to have the view watch its model for changes and update accordingly: `this.listenTo(this.model, "change", updateElement)` – Hart Simha Jan 14 '15 at 19:23