ctrlShiftBryan
ctrlShiftBryan

Reputation: 27740

Backbone.js: Can a View or Collection have an attribute?

Lets say I have a list of boys and girls names. This collection of names also has a 'Gender' property.

I want to put a 'SelectedGender' attribute on either the Collection or the View so that I can fire a custom event only when the Selected gender changes.

Can a View be extended to have a attribute that fires a change event?

Can a Collection be extended to have a attribute that fires a change event?

Or am I forced to create another Model that contains a collection? I don't actually have code I'm just thinking design at this point.

Upvotes: 1

Views: 1801

Answers (2)

stinkycheeseman
stinkycheeseman

Reputation: 45747

I don't think you need to create wrapper models for your collections. Just create a model that stores the name and the gender. Then, like @Paul mentioned, you can subscribe to the change event in the collection or in the view.

var nameModel = Backbone.Model.extend({
  defaults : function() {
    return {
      name   : "Andy",
      gender : "male"
    };
  }
} );

var nameCollection = Backbone.Collection.extend( {
  initialize : function ( args ) {
    var self = this;
    self.model.bind( "change:gender", function () {
      self.changeGender( self.model.get( "gender" ) );
    } );
  },

  changeGender : function( gender ) {
    // modify your collection somehow
  }
} );

var nameView = Backbone.View.extend( {
  initialize : function( args ) {
    var self = this;
    self.model.bind( "change:gender", function () {
      self.changeGender( self.model.get( "gender" ) );
    } );
    // in case you have a checkbox or something you want to bind the model change to:
    self.$( ".genderCheckbox" ).bind( "change", function( ev ) {
      self.model.set( { gender, self.$( ".genderCheckbox" ).val() } );
    } );
  },

  changeGender : function( gender ) {
     // Modify your view here
  }
} );

EDIT:

Rather than having 2 seperate collections depending on the gender of the name, why not have one collection of names with a method that returns just the boy names and a method that returns just the girl names?

ie:

getMaleNames : function() {
  return this.filter( function( name ) {
    return name.get( 'gender' ) == "male";
  } );
}

Upvotes: 1

Paul
Paul

Reputation: 18597

To answer your question: Can a view or collection be extended to have an attribute that fires a change event, the answer is no and yes.

No, you can't do view.set({attr: value}) or collection.set({attr: value})

You can, however have a view or collection fire events by extending Backbone.Events.

YourView = Backbone.View.extend({});
_.extend(YourView, Backbone.Events);

var view = new YourView();
view.bind('SelectedGenderChanged', function() {
  console.log('SelectedGenderChanged event fired!');
});

//somewhere else in your code
view.trigger('SelectedGenderChanged');

However, there might be a better way to design this.

If the selected gender changes when a user makes a selection from a combo box, then you can subscribe to the combo box change event in your view, and then have your view make any changes that need to be done at that time.

Upvotes: 4

Related Questions