Many of the properties of Backbone classes have the option of being defined as functions instead of as primitives. In fact, we've already seen one instance of this behavior in the url
property of Models
and Collections
. As we learned in Chapter 3, Accessing Server Data with Models, this property can be a simple string, but if you have a more complex URL that requires logic to generate, you can instead use a function that returns a string.
This same approach can be used with a number of Backbone properties, including the following:
defaults
url
urlRoot
attributes
className
events
id
tagName
routes
For instance, let's say you wanted to have View
that can generate either <input>
or <select>
based on whether or not it has Collection
. By using a function in place of a string for our Views
tagName
property of the Views
, we can do exactly that:
var VariableTagView = Backbone.View.extend({ tagName: function() { if (this.collection) { return 'select'; } else { return 'input'; } } });
The Collection
class also has a property that can be replaced with a function, but unlike the other properties, this one isn't normally a primitive… it's a Backbone Model
subclass. As discussed in Chapter 4, Organizing Models with Collections, the model property of a Collection
class determines what type of Model
will be created by that Collection
. Normally, each Collection
class can have only a single model property and thus, can only create a single type of Model
.
However, there is a way around this limitation: If we replace the model property of our Collection
with a function that returns new Models
, Backbone will cheerfully overlook the fact that the model
property isn't actually a Model
subclass at all. For example, let's say our server has a "/book" API endpoint that returns JSON for two types of books: fiction and nonfiction. Let's also say that we have two different Model
classes, one for each type of book. If we wanted to be able to have a Collection
class that fetches the JSON for both types of books from a single end point but uses the appropriate model
function to instantiate each type of book, we could use a factory "model" function, as follows:
var FictionBook = Backbone.Model.extend({ // insert logic for fiction books here}); var NonFictionBook = Backbone.Model.extend({ // insert logic for non-fiction books here}); var FictionAndNonFictionBooks = Backbone.Collection.extend({ model: function(attributes, options) { if (attributes.isFiction) { return new FictionBook(attributes, options); } else { return new NonFictionBook(attributes, options); } }, url: '/book'});
3.15.211.34