styler
styler

Reputation: 16491

Backbone Model defaults not being overwrote by Model data

Learning Backbone at the moment and currently at a very basic level, I have set up a model, view and collection relating to person data and want to template this data out using Handlebars. So I've created my Person Model with default values, created a People Collection that listens for the Person Collection and my Person View which should output my model data. At the moment however only my default data is being output so I guess I'm doing something wrong. If anyone could offer any advice at all that would be great!

JS

//Model
var Person = Backbone.Model.extend({

  //Default Attributes
  defaults: {
    'name': 'Joe',
    'age': 29,
    'gender': 'male',
    'country': 'UK'
  }

});

//Instantiate the Person Model
var person = new Person();


//Create People Collection to hold multiple Person Models
var PeopleCollection = Backbone.Collection.extend({
  model: Person
});


//Add multiple Person Models into People Collection, check out the [] as this is content in JSON style
var peopleCollection = new PeopleCollection([
  {
    'name': 'James',
    'age': 34,
    'gender': 'male',
    'country': 'USA'
  },
  {
    'name': 'Jason',
    'age': 31,
    'gender': 'male',
    'country': 'Australia'
  }
]);

//View
var PersonView = Backbone.View.extend({

//   tagName: '',

  //Get the template markup
  template: $('#person-template').html(),

  initialize: function() {    
    this.$el.personCtn = $('#person-ctn');

//     console.log('His name is ' + this.model.get('name') );

    console.log(this.model);

    this.render();
  },

  render: function() {

    //Compile this.template === #person-template
    var template = Handlebars.compile(this.template);

    //Actually add to page
    this.$el.personCtn.html( template( this.model.toJSON() ) );


    return this;
  }

});

//Instantiate the Person View
var personView = new PersonView({
  'model': person
});

Link to demo http://jsbin.com/oFIxizuq/6/edit?html,js,output

Upvotes: 1

Views: 56

Answers (2)

fbynite
fbynite

Reputation: 2661

The problem is you are passing the person model to your view, which was created with default values when you called the following code:

// A Person model with default values
var person = new Person();

// You then pass the person model to the PersonView
var personView = new PersonView({
  'model': person
});

I believe you meant to pass the peopleCollection to the Backbone.View. Which would look like:

//Instantiate the Person View
var personView = new PersonView({
  collection: peopleCollection
});

But maybe since it's a collection we will it call it peopleView.

//View
var PeopleView = Backbone.View.extend({

  //Get the template markup
  template: $('#person-template').html(),

  render: function() {
    var template = Handlebars.compile(this.template);
    var view = this;

    // render each model with the template  
    this.collection.each(function(model) {
      view.$el.append(template(model.toJSON()));
    });

    return this;
  }

});

// Create the view and pass the peopleCollection
var peopleView = new PeopleView({
  collection: peopleCollection
});

A fiddle from your example: http://jsbin.com/oFIxizuq/8/edit

Some side suggestions:

  1. Instead of this.$el.personCtn = $('#person-ctn') you should assign an el property to your view (if you know the element exists) when you are instantiate or extend the view, so new PeopleView({el:'#person-ctn'}); would be one way. Then within the view you can access that element using this.$el.

  2. You can move the Handlebars.compile into the template property. such as, template:Handlebars.compile($('#person-template').html())

So another way to use your code if you want to supply an el property is:

var PeopleView = Backbone.View.extend({
  el:'#person-ctn',

 template: Handlebars.compile($('#person-template').html()),

 render: function() {
   var view = this;

   this.collection.each(function(model) {
     view.$el.append(view.template(model.toJSON()));
   });

   return this;
  }

});

var peopleView = new PeopleView({
  collection: peopleCollection
});

peopleView.render();

Guess I can add that example for you as well http://jsbin.com/opuroNO/1/edit

Upvotes: 2

Alessandro Minoccheri
Alessandro Minoccheri

Reputation: 35973

I have change the logic of your app, well, in your app there are some problem. You don't use collection.
To use collection you need to add elements by default like a model.
Other problem you print the model not the collection and you print always a line because using html() you override always your html.

this is the solution that I have create for you. It works fine for me.

DEMO

try please:

//Model
var Person = Backbone.Model.extend({

  //Default Attributes
  defaults: {
    'name': 'Joe',
    'age': 29,
    'gender': 'male',
    'country': 'UK'
  }

});



//Create People Collection to hold multiple Person Models
var PeopleCollection = Backbone.Collection.extend({
  model: Person,
  addPerson: function(elements, options) {
                return this.add(elements, options);
        }
});

//View
var PersonView = Backbone.View.extend({

//   tagName: '',

  //Get the template markup
  template: $('#person-template').html(),

  initialize: function() {  
    this.collection = new PeopleCollection([],{ });  
    var p = { name: 'James',age: 34, gender: 'male' , country: 'USA'}; 
    var p2 = { name: 'Jason',age: 31, gender: 'male' , country: 'Australia'};
    this.elementModel = new Person(p);
    this.collection.addPerson(this.elementModel);
    this.elementModel = new Person(p2);
    this.collection.addPerson(this.elementModel);


    this.$el.personCtn = $('#person-ctn');

//     console.log('His name is ' + this.model.get('name') );

    console.log(this.collection);

    this.render();
  },

  render: function() {

    //Compile this.template === #person-template
    var template = Handlebars.compile(this.template);
    var here = this;
    //Actually add to page
    $.each( this.collection.models , function( key, value ) {
        console.log(value);
       here.$el.personCtn.append( template( value.toJSON() ) );
    });


    return this;
  }

});

//Instantiate the Person View
var personView = new PersonView({

});

Upvotes: 0

Related Questions