Skip to content
Branch: master
Go to file
Code

Latest commit

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
 
 
 
 

README.md

Backbone.js Subviews

Version 0.7.0

Extends Backbone.View with support for nested subviews that can be reused and cleaned up when need be. (helps mitigate ghosted views)

Features

  • Cleanup views when no longer needed
  • Provided access to parent views
  • Add additional methods to help with reusing Views
  • Keeps views uninitialized until needed
  • Propagates model to subviews
  • Listen to models/collections by defining them in a hash
  • And more...

Using Subviews

var MySubview = Backbone.View.extend({
	
	render: function(){
		console.log(this.parentView.className) // 'my-view'
		console.log(this.viewName) // 'my-subview'
	},
	
	cleanup: function(){
		console.log('perform cleanup')
		// such as this.stopListening(this.model)
	}
});

var MyView = Backbone.View.extend({
	
	className: 'my-view',
	 
	initialize: function(){
		this.sv('my-subview', MySubview).renderTo(this)
	},
	
	render: function(){
	
		// render the child view
		this.sv('my-subview').render();
	
		return this;
	}
})

When you remove a view, all subviews will be informed and told to cleanup

MyView.remove() // MySubview:'perform cleanup'

You can reuse views too instead of recreating over and over.

var MyListSubivew = Backbone.View.extend({});

var MyListView = Backbone.View.extend({
	
	render: function(){
	
		this.$el.html('')
		// assuming this view has a collection...
		this.collection.each(this.addOne, this)
	
		return this;
	},
	
	addOne: function(model){
		
		let viewName = 'item-'+model.id
		
		// MyListSubivew will only be initialized once for the given viewName
		this.sv(viewName, MyListSubivew)
			.setModel(model)
			.renderTo(this)
		
		// if you data/options are needed upon initialization of the view, you can do This
		// this.sv(viewName, MyListSubivew, {model: model, another:'option'})
	}
})

Defining Views

Since creating and appending subviews to a view is a common routine, backbone.subviews provides a way to setup and render them automatically for you.

var View1 = Backbone.View.extend({className: 'v1'});
var View2 = Backbone.View.extend({className: 'v2'});
var BadgeView = Backbone.View.extend({className: 'badge'});
var ViewColl = Backbone.View.extend({className: 'v-coll', tagName: 'ul'});

var RootView = Backbone.View.extend({

	className: 'rootview',
	template: '<h1 class="title">Title</h1>',

	views: {
		'view1': View1,
		'view2': View2,
		'badge': {
			view: BadgeView,
			appendTo: '.title'
		},
		'view-collection': {
			view: ViewColl,
			setModel: function(v, model){
				v.collection = model.get('a-child-collection')
			}
		}
	}

});

When the RootView is rendered, all the views defined in views will be initialized, appended to RootView and then their render() method called.

This will give us the following DOM structure

<div class="rootview">
	<h1 class="title">Title<div class="badge"></div></h1>
	<div class="v1"></div>
	<div class="v2"></div>
	<ul class="v-coll"></ul>
</div>

If you override render you'll need to remember to call renderViews() on your own.

Attaching Listeners to Model/Collections

It is common practice for a view to listen to a model or collection for changes and react accordingly. This can be done by specifying a hash of events like so:

listeners: {
	model: {
		'change': 'render',
		'destroy': 'remove',
		'reset': function(){
			// inline function also supported
		}
	},
	collection: {},
	'name-of-child-collection': {}
}

// the above is the equivalent of doing this manually
this.listenTo(this.model, 'change', this.render)
this.listenTo(this.model, 'destroy', this.remove)
this.listenTo(this.model, 'rest', function(){})

You'll notice above that Child Collection is supported. The third listener would evaluate to:

this.model.get('name-of-child-collection')

Methods & References

There are some useful methods added to Backbone.Views

.sv() or .subview() - save and access subviews

.renderTo() - render and append to a backbone view (or jquery element)

.empty() - clears the view of contents

.inDOM() - whether or not the view is presented in the DOM or just stored in memory

.reRender() - will only render if in the DOM

.renderViews() - init and append (if needed) and then render all defined views (this.views)

.forEachView(callback) - perform an action on all defined views

.renderTemplate() - will take this.template and merge with this.model and append to el. (See backbone.template-data)

.parentView - a reference to the parent view of this child

.parent(viewName, returnPromise=false) - will traverse up parent views until matched view name. Use root to get the top level view. Dot notation is supported for traversing up to a parent and then down to a subview.

.viewName - the name the child is stored under in the parent

Changelog

v0.7.0

  • Defined views:{} will get setModel called upon initialization (if they have it)
  • Model/Collection listeners can be defined and applied automatically

v0.6.2

  • collection: this.collection also passed to view upon creation (previously only this.model was given)

v0.6.1

  • fix .sv alias not passing opts arg

v0.6.0

  • return this in setModel for chainability
  • add renderTo method
  • view arg in .sv() can be uninitialized - the view will only initialize once.
  • defined view in views has setModel option available

v0.5.0

  • new .parent(viewName, returnPromise=false) method for traversing up the parent views to the one matching the given name

v0.4.0

  • add support for defining and automating subviews on a view

License

MIT © Kevin Jantzer - Blackstone Publishing

About

Extends Backbone.View with support for nested subviews that can be reused and cleaned up when need be.

Topics

Resources

Releases

No releases published
You can’t perform that action at this time.