Академический Документы
Профессиональный Документы
Культура Документы
Backbone.js
start
Sync
Backbone.sync
Backbone.ajax
Backbone.emulateHTTP
Backbone.emulateJSON
View
extend
Backbone.jsgivesstructuretowebapplicationsbyprovidingmodelswithkeyvalue
constructor / initialize
bindingandcustomevents,collectionswitharichAPIofenumerablefunctions,
el
viewswithdeclarativeeventhandling,andconnectsitalltoyourexistingAPIovera
$el
setElement
RESTfulJSONinterface.
attributes
$ (jQuery)
template
render
TheprojectishostedonGitHub,andtheannotatedsourcecodeisavailable,aswell
asanonlinetestsuite,anexampleapplication,alistoftutorialsandalonglistofreal
remove
worldprojectsthatuseBackbone.BackboneisavailableforuseundertheMIT
events
softwarelicense.
delegateEvents
undelegateEvents
YoucanreportbugsanddiscussfeaturesontheGitHubissuespage,onFreenode
Utility
Backbone.noConflict
thewikiorsendtweetsto@documentcloud.
Backbone.$
F.A.Q.
BackboneisanopensourcecomponentofDocumentCloud.
Why Backbone?
More Than One Way To Do It
Nested Models & Collections
Loading Bootstrapped Models
Downloads&Dependencies
Extending Backbone
Traditional MVC
Binding "this"
DevelopmentVersion(1.3.2)
72kb,Fullsource,tonsofcomments
Examples
ProductionVersion(1.3.2)
DocumentCloud
USA Today
7.5kb,Packedandgzipped
(SourceMap)
Todos
EdgeVersion(master)
Unreleased,useatyourownrisk
Rdio
Hulu
Quartz
Earth
Vox
Gawker Media
Backbone'sonlyharddependencyisUnderscore.js(>=1.8.3).ForRESTfulpersistence
andDOMmanipulationwithBackbone.View,includejQuery(>=1.11.0),andjson2.js
Flow
forolderInternetExplorersupport.(MimicsoftheUnderscoreandjQueryAPIs,such
Gilt Groupe
asLodashandZepto,willalsotendtowork,withvaryingdegreesofcompatibility.)
Enigma
NewsBlur
WordPress.com
Foursquare
Bitbucket
Disqus
GettingStarted
Delicious
WhenworkingonawebapplicationthatinvolvesalotofJavaScript,oneofthefirst
Khan Academy
thingsyoulearnistostoptyingyourdatatotheDOM.It'salltooeasytocreate
IRCCloud
Pitchfork
JavaScriptapplicationsthatendupastangledpilesofjQueryselectorsandcallbacks,
Spin
alltryingfranticallytokeepdatainsyncbetweentheHTMLUI,yourJavaScriptlogic,
ZocDoc
andthedatabaseonyourserver.Forrichclientsideapplications,amorestructured
Walmart Mobile
Groupon Now!
approachisoftenhelpful.
Basecamp
Slavery Footprint
Stripe
Airbnb
WithBackbone,yourepresentyourdataasModels,whichcanbecreated,validated,
destroyed,andsavedtotheserver.WheneveraUIactioncausesanattributeofa
SoundCloud Mobile
modeltochange,themodeltriggersa"change"eventalltheViewsthatdisplaythe
- Art.sy
model'sstatecanbenotifiedofthechange,sothattheyareabletorespond
Pandora
accordingly,rerenderingthemselveswiththenewinformation.InafinishedBackbone
Inkling
Code School
app,youdon'thavetowritethegluecodethatlooksintotheDOMtofindanelement
CloudApp
withaspecificid,andupdatetheHTMLmanuallywhenthemodelchanges,the
SeatGeek
viewssimplyupdatethemselves.
Easel
- Jolicloud
Salon.io
Philosophically,Backboneisanattempttodiscovertheminimalsetofdatastructuring
TileMill
(modelsandcollections)anduserinterface(viewsandURLs)primitivesthatare
Blossom
Trello
Tzigla
Change Log
http://backbonejs.org/#changelog
generallyusefulwhenbuildingwebapplicationswithJavaScript.Inanecosystem
whereoverarching,decideseverythingforyouframeworksarecommonplace,and
manylibrariesrequireyoursitetobereorganizedtosuittheirlook,feel,anddefault
behaviorBackboneshouldcontinuetobeatoolthatgivesyouthefreedomto
1/57
3/16/2016
Backbone.js
designthefullexperienceofyourwebapplication.
Ifyou'renewhere,andaren'tyetquitesurewhatBackboneisfor,startbybrowsing
thelistofBackbonebasedprojects.
Manyofthecodeexamplesinthisdocumentationarerunnable,becauseBackboneis
includedonthispage.Clicktheplaybuttontoexecutethem.
ModelsandViews
ThesinglemostimportantthingthatBackbonecanhelpyouwithiskeepingyour
businesslogicseparatefromyouruserinterface.Whenthetwoareentangled,change
ishardwhenlogicdoesn'tdependonUI,yourinterfacebecomeseasiertoworkwith.
Model
View
Orchestratesdataandbusinesslogic.
ListensforchangesandrendersUI.
Loadsandsavesfromtheserver.
Handlesuserinputandinteractivity.
Emitseventswhendatachanges.
Sendscapturedinputtothemodel.
Collections
ACollectionhelpsyoudealwithagroupofrelatedmodels,handlingtheloadingand
savingofnewmodelstotheserverandprovidinghelperfunctionsforperforming
aggregationsorcomputationsagainstalistofmodels.Asidefromtheirownevents,
collectionsalsoproxythroughalloftheeventsthatoccurtomodelswithinthem,
allowingyoutolisteninoneplaceforanychangethatmighthappentoanymodelin
thecollection.
APIIntegration
BackboneispreconfiguredtosyncwithaRESTfulAPI.SimplycreateanewCollection
withthe url ofyourresourceendpoint:
http://backbonejs.org/#changelog
2/57
3/16/2016
Backbone.js
varBooks=Backbone.Collection.extend({
url:'/books'
});
TheCollectionandModelcomponentstogetherformadirectmappingofREST
resourcesusingthefollowingmethods:
GET/books/....collection.fetch();
POST/books/....collection.create();
GET/books/1...model.fetch();
PUT/books/1...model.save();
DEL/books/1...model.destroy();
WhenfetchingrawJSONdatafromanAPI,aCollectionwillautomaticallypopulate
itselfwithdataformattedasanarray,whileaModelwillautomaticallypopulateitself
withdataformattedasanobject:
[{"id":1}].....populatesaCollectionwithonemodel.
{"id":1}.......populatesaModelwithoneattribute.
However,it'sfairlycommontoencounterAPIsthatreturndatainadifferentformat
thanwhatBackboneexpects.Forexample,considerfetchingaCollectionfroman
APIthatreturnstherealdataarraywrappedinmetadata:
{
"page":1,
"limit":10,
"total":2,
"books":[
{"id":1,"title":"PrideandPrejudice"},
{"id":4,"title":"TheGreatGatsby"}
]
}
ViewRendering
EachViewmanagestherenderinganduserinteractionwithinitsownDOMelement.If
you'restrictaboutnotallowingviewstoreachoutsideofthemselves,ithelpskeepyour
interfaceflexibleallowingviewstoberenderedinisolationinanyplacewherethey
mightbeneeded.
BackboneremainsunopinionatedabouttheprocessusedtorenderViewobjectsand
theirsubviewsintoUI:youdefinehowyourmodelsgettranslatedintoHTML(orSVG,
orCanvas,orsomethingevenmoreexotic).Itcouldbeasprosaicasasimple
Underscoretemplate,orasfancyastheReactvirtualDOM.Somebasicapproaches
torenderingviewscanbefoundintheBackboneprimer.
http://backbonejs.org/#changelog
3/57
3/16/2016
Backbone.js
RoutingwithURLs
Inrichwebapplications,westillwanttoprovidelinkable,bookmarkable,andshareable
URLstomeaningfullocationswithinanapp.UsetheRoutertoupdatethebrowser
URLwhenevertheuserreachesanew"place"inyourappthattheymightwantto
bookmarkorshare.Conversely,theRouterdetectschangestotheURLsay,
pressingthe"Back"buttonandcantellyourapplicationexactlywhereyouarenow.
Backbone.Events
Eventsisamodulethatcanbemixedintoanyobject,givingtheobjecttheabilityto
bindandtriggercustomnamedevents.Eventsdonothavetobedeclaredbeforethey
arebound,andmaytakepassedarguments.Forexample:
varobject={};
_.extend(object,Backbone.Events);
object.on("alert",function(msg){
alert("Triggered"+msg);
});
object.trigger("alert","anevent");
Forexample,tomakeahandyeventdispatcherthatcancoordinateeventsamong
differentareasofyourapplication: vardispatcher=_.clone(Backbone.Events)
on
object.on(event,callback,[context])
Alias:bind
Bindacallbackfunctiontoanobject.Thecallbackwillbeinvokedwhenevertheevent
isfired.Ifyouhavealargenumberofdifferenteventsonapage,theconventionisto
usecolonstonamespacethem: "poll:start" ,or "change:selection" .Theevent
stringmayalsobeaspacedelimitedlistofseveralevents...
book.on("change:titlechange:author",...);
AllBackboneeventmethodsalsosupportaneventmapsyntax,asanalternativeto
positionalarguments:
book.on({
"change:author":authorPane.update,
"change:titlechange:subtitle":titleView.update,
"destroy":bookView.remove
});
http://backbonejs.org/#changelog
4/57
3/16/2016
Backbone.js
off
object.off([event],[callback],[context])
Alias:unbind
Removeapreviouslyboundcallbackfunctionfromanobject.Ifnocontextis
specified,alloftheversionsofthecallbackwithdifferentcontextswillberemoved.If
nocallbackisspecified,allcallbacksfortheeventwillberemoved.Ifnoeventis
specified,callbacksforalleventswillberemoved.
//Removesjustthe`onChange`callback.
object.off("change",onChange);
//Removesall"change"callbacks.
object.off("change");
//Removesthe`onChange`callbackforallevents.
object.off(null,onChange);
//Removesallcallbacksfor`context`forallevents.
object.off(null,null,context);
//Removesallcallbackson`object`.
object.off();
trigger
object.trigger(event,[*args])
Triggercallbacksforthegivenevent,orspacedelimitedlistofevents.Subsequent
argumentstotriggerwillbepassedalongtotheeventcallbacks.
once
object.once(event,callback,[context])
Justlikeon,butcausestheboundcallbacktofireonlyoncebeforebeingremoved.
Handyforsaying"thenexttimethatXhappens,dothis".Whenmultipleeventsare
passedinusingthespaceseparatedsyntax,theeventwillfireonceforeveryevent
youpassedin,notonceforacombinationofallevents
listenTo
object.listenTo(other,event,callback)
Tellanobjecttolistentoaparticulareventonanotherobject.Theadvantageof
usingthisform,insteadof other.on(event,callback,object) ,isthatlistenToallows
theobjecttokeeptrackoftheevents,andtheycanberemovedallatoncelateron.
Thecallbackwillalwaysbecalledwithobjectascontext.
view.listenTo(model,'change',view.render);
stopListening
object.stopListening([other],[event],[callback])
Tellanobjecttostoplisteningtoevents.EithercallstopListeningwithnoarguments
tohavetheobjectremoveallofitsregisteredcallbacks...orbemorepreciseby
tellingittoremovejusttheeventsit'slisteningtoonaspecificobject,oraspecific
event,orjustaspecificcallback.
view.stopListening();
view.stopListening(model);
listenToOnce
object.listenToOnce(other,event,callback)
JustlikelistenTo,butcausestheboundcallbacktofireonlyoncebeforebeing
removed.
CatalogofEvents
Here'sthecompletelistofbuiltinBackboneevents,witharguments.You'realsofree
totriggeryourowneventsonModels,CollectionsandViewsasyouseefit.The
Backbone objectitselfmixesin Events ,andcanbeusedtoemitanyglobaleventsthat
yourapplicationneeds.
"add"(model,collection,options)whenamodelisaddedtoacollection.
http://backbonejs.org/#changelog
5/57
3/16/2016
Backbone.js
"remove"(model,collection,options)whenamodelisremovedfromacollection.
"update"(collection,options)singleeventtriggeredafteranynumberofmodelshavebeenadded
orremovedfromacollection.
"reset"(collection,options)whenthecollection'sentirecontentshavebeenreset.
"sort"(collection,options)whenthecollectionhasbeenresorted.
"change"(model,options)whenamodel'sattributeshavechanged.
"change:[attribute]"(model,value,options)whenaspecificattributehasbeenupdated.
"destroy"(model,collection,options)whenamodelisdestroyed.
"request"(model_or_collection,xhr,options)whenamodelorcollectionhasstartedarequestto
theserver.
"sync"(model_or_collection,response,options)whenamodelorcollectionhasbeen
successfullysyncedwiththeserver.
"error"(model_or_collection,response,options)whenamodel'sorcollection'srequesttothe
serverhasfailed.
"invalid"(model,error,options)whenamodel'svalidationfailsontheclient.
"route:[name]"(params)Firedbytherouterwhenaspecificrouteismatched.
"route"(route,params)Firedbytherouterwhenanyroutehasbeenmatched.
"route"(router,route,params)Firedbyhistorywhenanyroutehasbeenmatched.
"all"thisspecialeventfiresforanytriggeredevent,passingtheeventnameasthefirstargument
followedbyalltriggerarguments.
Generallyspeaking,whencallingafunctionthatemitsanevent( model.set ,
collection.add ,andsoon...),ifyou'dliketopreventtheeventfrombeingtriggered,
Backbone.Model
ModelsaretheheartofanyJavaScriptapplication,containingtheinteractivedataas
wellasalargepartofthelogicsurroundingit:conversions,validations,computed
properties,andaccesscontrol.YouextendBackbone.Modelwithyourdomain
specificmethods,andModelprovidesabasicsetoffunctionalityformanaging
changes.
Thefollowingisacontrivedexample,butitdemonstratesdefiningamodelwitha
custommethod,settinganattribute,andfiringaneventkeyedtochangesinthat
specificattribute.Afterrunningthiscodeonce, sidebar willbeavailableinyour
browser'sconsole,soyoucanplayaroundwithit.
varSidebar=Backbone.Model.extend({
promptColor:function(){
varcssColor=prompt("PleaseenteraCSScolor:");
this.set({color:cssColor});
}
});
window.sidebar=newSidebar;
sidebar.on('change:color',function(model,color){
$('#sidebar').css({background:color});
});
sidebar.set({color:'white'});
sidebar.promptColor();
extend
Backbone.Model.extend(properties,[classProperties])
TocreateaModelclassofyourown,youextendBackbone.Modelandprovide
instanceproperties,aswellasoptionalclassPropertiestobeattacheddirectlytothe
constructorfunction.
extendcorrectlysetsuptheprototypechain,sosubclassescreatedwithextendcan
befurtherextendedandsubclassedasfarasyoulike.
http://backbonejs.org/#changelog
6/57
3/16/2016
Backbone.js
varNote=Backbone.Model.extend({
initialize:function(){...},
author:function(){...},
coordinates:function(){...},
allowedToEdit:function(account){
returntrue;
}
});
varPrivateNote=Note.extend({
allowedToEdit:function(account){
returnaccount.owns(this);
}
});
varNote=Backbone.Model.extend({
set:function(attributes,options){
Backbone.Model.prototype.set.apply(this,arguments);
...
}
});
constructor/initialize
newModel([attributes],[options])
Whencreatinganinstanceofamodel,youcanpassintheinitialvaluesofthe
attributes,whichwillbesetonthemodel.Ifyoudefineaninitializefunction,itwillbe
invokedwhenthemodeliscreated.
newBook({
title:"OneThousandandOneNights",
author:"Scheherazade"
});
Inrarecases,ifyou'relookingtogetfancy,youmaywanttooverrideconstructor,
whichallowsyoutoreplacetheactualconstructorfunctionforyourmodel.
varLibrary=Backbone.Model.extend({
constructor:function(){
this.books=newBooks();
Backbone.Model.apply(this,arguments);
},
parse:function(data,options){
this.books.reset(data.books);
returndata.library;
}
});
get
model.get(attribute)
Getthecurrentvalueofanattributefromthemodel.Forexample: note.get("title")
http://backbonejs.org/#changelog
7/57
3/16/2016
Backbone.js
set
model.set(attributes,[options])
Setahashofattributes(oneormany)onthemodel.Ifanyoftheattributeschangethe
model'sstate,a "change" eventwillbetriggeredonthemodel.Changeeventsfor
specificattributesarealsotriggered,andyoucanbindtothoseaswell,forexample:
change:title ,and change:content .Youmayalsopassindividualkeysandvalues.
note.set({title:"March20",content:"Inhiseyessheeclipses..."});
book.set("title","AScandalinBohemia");
escape
model.escape(attribute)
Similartoget,butreturnstheHTMLescapedversionofamodel'sattribute.Ifyou're
interpolatingdatafromthemodelintoHTML,usingescapetoretrieveattributeswill
preventXSSattacks.
varhacker=newBackbone.Model({
name:"<script>alert('xss')</script>"
});
alert(hacker.escape('name'));
has
model.has(attribute)
unset
model.unset(attribute,[options])
Removeanattributebydeletingitfromtheinternalattributeshash.Firesa "change"
eventunless silent ispassedasanoption.
clear
model.clear([options])
id
model.id
Aspecialpropertyofmodels,theidisanarbitrarystring(integeridorUUID).Ifyouset
theidintheattributeshash,itwillbecopiedontothemodelasadirectproperty.
Modelscanberetrievedbyidfromcollections,andtheidisusedtogeneratemodel
URLsbydefault.
idAttribute
model.idAttribute
Amodel'suniqueidentifierisstoredunderthe id attribute.Ifyou'redirectly
communicatingwithabackend(CouchDB,MongoDB)thatusesadifferentuniquekey,
youmaysetaModel's idAttribute totransparentlymapfromthatkeyto id .
varMeal=Backbone.Model.extend({
idAttribute:"_id"
});
varcake=newMeal({_id:1,name:"Cake"});
alert("Cakeid:"+cake.id);
cid
model.cid
Aspecialpropertyofmodels,thecidorclientidisauniqueidentifierautomatically
assignedtoallmodelswhenthey'refirstcreated.Clientidsarehandywhenthemodel
hasnotyetbeensavedtotheserver,anddoesnotyethaveitseventualtrueid,but
alreadyneedstobevisibleintheUI.
attributes
model.attributes
Theattributespropertyistheinternalhashcontainingthemodel'sstateusually
http://backbonejs.org/#changelog
8/57
3/16/2016
Backbone.js
(butnotnecessarily)aformoftheJSONobjectrepresentingthemodeldataonthe
server.It'softenastraightforwardserializationofarowfromthedatabase,butitcould
alsobeclientsidecomputedstate.
Pleaseusesettoupdatetheattributesinsteadofmodifyingthemdirectly.Ifyou'dlike
toretrieveandmungeacopyofthemodel'sattributes,use _.clone(model.attributes)
instead.
DuetothefactthatEventsacceptsspaceseparatedlistsofevents,attributenamesshouldnotinclude
spaces.
changed
model.changed
Thechangedpropertyistheinternalhashcontainingalltheattributesthathave
changedsinceitslastset.Pleasedonotupdatechangeddirectlysinceitsstateis
internallymaintainedbyset.Acopyofchangedcanbeacquiredfrom
changedAttributes.
defaults
model.defaultsormodel.defaults()
Thedefaultshash(orfunction)canbeusedtospecifythedefaultattributesforyour
model.Whencreatinganinstanceofthemodel,anyunspecifiedattributeswillbeset
totheirdefaultvalue.
varMeal=Backbone.Model.extend({
defaults:{
"appetizer":"caesarsalad",
"entree":"ravioli",
"dessert":"cheesecake"
}
});
alert("Dessertwillbe"+(newMeal).get('dessert'));
RememberthatinJavaScript,objectsarepassedbyreference,soifyouincludeanobjectasadefault
value,itwillbesharedamongallinstances.Instead,definedefaultsasafunction.
toJSON
model.toJSON([options])
Returnashallowcopyofthemodel'sattributesforJSONstringification.Thiscanbe
usedforpersistence,serialization,orforaugmentationbeforebeingsenttotheserver.
Thenameofthismethodisabitconfusing,asitdoesn'tactuallyreturnaJSONstring
butI'mafraidthatit'sthewaythattheJavaScriptAPIforJSON.stringifyworks.
varartist=newBackbone.Model({
firstName:"Wassily",
lastName:"Kandinsky"
});
artist.set({birthday:"December16,1866"});
alert(JSON.stringify(artist));
sync
model.sync(method,model,[options])
UsesBackbone.synctopersistthestateofamodeltotheserver.Canbeoverridden
forcustombehavior.
fetch
model.fetch([options])
Mergesthemodel'sstatewithattributesfetchedfromtheserverbydelegatingto
Backbone.sync.ReturnsajqXHR.Usefulifthemodelhasneverbeenpopulatedwith
data,orifyou'dliketoensurethatyouhavethelatestserverstate.Triggersa
"change" eventiftheserver'sstatediffersfromthecurrentattributes. fetch accepts
success and error callbacksintheoptionshash,whicharebothpassed (model,
response,options) asarguments.
//Pollevery10secondstokeepthechannelmodeluptodate.
setInterval(function(){
channel.fetch();
},10000);
http://backbonejs.org/#changelog
9/57
3/16/2016
Backbone.js
save
model.save([attributes],[options])
Saveamodeltoyourdatabase(oralternativepersistencelayer),bydelegatingto
Backbone.sync.ReturnsajqXHRifvalidationissuccessfuland false otherwise.The
attributeshash(asinset)shouldcontaintheattributesyou'dliketochangekeys
thataren'tmentionedwon'tbealteredbut,acompleterepresentationofthe
resourcewillbesenttotheserver.Aswith set ,youmaypassindividualkeysand
valuesinsteadofahash.Ifthemodelhasavalidatemethod,andvalidationfails,the
modelwillnotbesaved.IfthemodelisNew,thesavewillbea "create" (HTTP POST ),
ifthemodelalreadyexistsontheserver,thesavewillbean "update" (HTTP PUT ).
Ifinstead,you'donlylikethechangedattributestobesenttotheserver,call
model.save(attrs,{patch:true}) .You'llgetanHTTP PATCH requesttotheserver
withjustthepassedinattributes.
Calling save withnewattributeswillcausea "change" eventimmediately,a
"request" eventastheAjaxrequestbeginstogototheserver,anda "sync" event
destroy
model.destroy([options])
UnderscoreMethods(9)
BackboneproxiestoUnderscore.jstoprovide9objectfunctionson
Backbone.Model.Theyaren'talldocumentedhere,butyoucantakealookatthe
Underscoredocumentationforthefulldetails
keys
values
pairs
http://backbonejs.org/#changelog
10/57
3/16/2016
Backbone.js
invert
pick
omit
chain
isEmpty
user.pick('first_name','last_name','email');
chapters.keys().join(',');
validate
model.validate(attributes,options)
Thismethodisleftundefinedandyou'reencouragedtooverrideitwithanycustom
validationlogicyouhavethatcanbeperformedinJavaScript.Bydefault save checks
validatebeforesettinganyattributesbutyoumayalsotell set tovalidatethenew
attributesbypassing {validate:true} asanoption.
Thevalidatemethodreceivesthemodelattributesaswellasanyoptionspassedto
set or save .Iftheattributesarevalid,don'treturnanythingfromvalidateiftheyare
invalidreturnanerrorofyourchoosing.Itcanbeassimpleasastringerrormessage
tobedisplayed,oracompleteerrorobjectthatdescribestheerrorprogrammatically.If
validatereturnsanerror, save willnotcontinue,andthemodelattributeswillnotbe
modifiedontheserver.Failedvalidationstriggeran "invalid" event,andsetthe
validationError propertyonthemodelwiththevaluereturnedbythismethod.
varChapter=Backbone.Model.extend({
validate:function(attrs,options){
if(attrs.end<attrs.start){
return"can'tendbeforeitstarts";
}
}
});
varone=newChapter({
title:"ChapterOne:TheBeginning"
});
one.on("invalid",function(model,error){
alert(model.get("title")+""+error);
});
one.save({
start:15,
end:10
});
"invalid" eventsareusefulforprovidingcoarsegrainederrormessagesatthe
modelorcollectionlevel.
validationError
model.validationError
Thevaluereturnedbyvalidateduringthelastfailedvalidation.
isValid
model.isValid()
Runvalidatetocheckthemodelstate.
varChapter=Backbone.Model.extend({
validate:function(attrs,options){
if(attrs.end<attrs.start){
return"can'tendbeforeitstarts";
}
}
});
varone=newChapter({
title:"ChapterOne:TheBeginning"
});
one.set({
start:15,
end:10
});
http://backbonejs.org/#changelog
11/57
3/16/2016
Backbone.js
if(!one.isValid()){
alert(one.get("title")+""+one.validationError);
}
url
model.url()
ReturnstherelativeURLwherethemodel'sresourcewouldbelocatedontheserver.
Ifyourmodelsarelocatedsomewhereelse,overridethismethodwiththecorrectlogic.
GeneratesURLsoftheform: "[collection.url]/[id]" bydefault,butyoumay
overridebyspecifyinganexplicit urlRoot ifthemodel'scollectionshouldn'tbetaken
intoaccount.
DelegatestoCollection#urltogeneratetheURL,somakesurethatyouhaveit
defined,oraurlRootproperty,ifallmodelsofthisclassshareacommonrootURL.A
modelwithanidof 101 ,storedinaBackbone.Collectionwitha url of
"/documents/7/notes" ,wouldhavethisURL: "/documents/7/notes/101"
urlRoot
model.urlRootormodel.urlRoot()
parse
model.parse(response,options)
parseiscalledwheneveramodel'sdataisreturnedbytheserver,infetch,andsave.
Thefunctionispassedtheraw response object,andshouldreturntheattributeshash
tobesetonthemodel.Thedefaultimplementationisanoop,simplypassingthrough
theJSONresponse.OverridethisifyouneedtoworkwithapreexistingAPI,orbetter
namespaceyourresponses.
Ifyou'reworkingwithaRailsbackendthathasaversionpriorto3.1,you'llnoticethat
itsdefault to_json implementationincludesamodel'sattributesunderanamespace.
TodisablethisbehaviorforseamlessBackboneintegration,set:
ActiveRecord::Base.include_root_in_json=false
clone
model.clone()
Returnsanewinstanceofthemodelwithidenticalattributes.
isNew
model.isNew()
Hasthismodelbeensavedtotheserveryet?Ifthemodeldoesnotyethavean id ,it
isconsideredtobenew.
hasChanged
model.hasChanged([attribute])
Hasthemodelchangedsinceitslastset?Ifanattributeispassed,returns true if
thatspecificattributehaschanged.
Notethatthismethod,andthefollowingchangerelatedones,areonlyusefulduringthecourseofa
"change" event.
book.on("change",function(){
if(book.hasChanged("title")){
...
}
});
changedAttributes
model.changedAttributes([attributes])
Retrieveahashofonlythemodel'sattributesthathavechangedsincethelastset,or
http://backbonejs.org/#changelog
12/57
3/16/2016
Backbone.js
false iftherearenone.Optionally,anexternalattributeshashcanbepassedin,
returningtheattributesinthathashwhichdifferfromthemodel.Thiscanbeusedto
figureoutwhichportionsofaviewshouldbeupdated,orwhatcallsneedtobemade
tosyncthechangestotheserver.
previous
model.previous(attribute)
previousAttributes
model.previousAttributes()
Returnacopyofthemodel'spreviousattributes.Usefulforgettingadiffbetween
versionsofamodel,orgettingbacktoavalidstateafteranerroroccurs.
Backbone.Collection
Collectionsareorderedsetsofmodels.Youcanbind "change" eventstobenotified
whenanymodelinthecollectionhasbeenmodified,listenfor "add" and "remove"
events, fetch thecollectionfromtheserver,anduseafullsuiteofUnderscore.js
methods.
Anyeventthatistriggeredonamodelinacollectionwillalsobetriggeredonthe
collectiondirectly,forconvenience.Thisallowsyoutolistenforchangestospecific
attributesinanymodelinacollection,forexample: documents.on("change:selected",
...)
extend
Backbone.Collection.extend(properties,[classProperties])
TocreateaCollectionclassofyourown,extendBackbone.Collection,providing
instanceproperties,aswellasoptionalclassPropertiestobeattacheddirectlytothe
collection'sconstructorfunction.
model
collection.model([attrs],[options])
Overridethispropertytospecifythemodelclassthatthecollectioncontains.Ifdefined,
youcanpassrawattributesobjects(andarrays)toadd,create,andreset,andthe
attributeswillbeconvertedintoamodelofthepropertype.
varLibrary=Backbone.Collection.extend({
model:Book
});
Acollectioncanalsocontainpolymorphicmodelsbyoverridingthispropertywitha
constructorthatreturnsamodel.
varLibrary=Backbone.Collection.extend({
model:function(attrs,options){
if(condition){
returnnewPublicDocument(attrs,options);
}else{
returnnewPrivateDocument(attrs,options);
}
}
});
http://backbonejs.org/#changelog
13/57
3/16/2016
Backbone.js
modelId
collection.modelId(attrs)
Overridethismethodtoreturnthevaluethecollectionwillusetoidentifyamodelgiven
itsattributes.Usefulforcombiningmodelsfrommultipletableswithdifferent
idAttribute valuesintoasinglecollection.
constructor/initialize
newBackbone.Collection([models],[options])
WhencreatingaCollection,youmaychoosetopassintheinitialarrayofmodels.The
collection'scomparatormaybeincludedasanoption.Passing false asthe
comparatoroptionwillpreventsorting.Ifyoudefineaninitializefunction,itwillbe
invokedwhenthecollectioniscreated.Thereareacoupleofoptionsthat,ifprovided,
areattachedtothecollectiondirectly: model and comparator .
Pass null for models tocreateanemptyCollectionwith options .
vartabs=newTabSet([tab1,tab2,tab3]);
varspaces=newBackbone.Collection(null,{
model:Space
});
models
collection.models
RawaccesstotheJavaScriptarrayofmodelsinsideofthecollection.Usuallyyou'll
wanttouse get , at ,ortheUnderscoremethodstoaccessmodelobjects,but
occasionallyadirectreferencetothearrayisdesired.
toJSON
collection.toJSON([options])
Returnanarraycontainingtheattributeshashofeachmodel(viatoJSON)inthe
collection.Thiscanbeusedtoserializeandpersistthecollectionasawhole.The
nameofthismethodisabitconfusing,becauseitconformstoJavaScript'sJSONAPI.
varcollection=newBackbone.Collection([
{name:"Tim",age:5},
{name:"Ida",age:26},
{name:"Rob",age:55}
]);
alert(JSON.stringify(collection));
sync
collection.sync(method,collection,[options])
UsesBackbone.synctopersistthestateofacollectiontotheserver.Canbe
overriddenforcustombehavior.
UnderscoreMethods(46)
BackboneproxiestoUnderscore.jstoprovide46iterationfunctionson
Backbone.Collection.Theyaren'talldocumentedhere,butyoucantakealookat
theUnderscoredocumentationforthefulldetails
Mostmethodscantakeanobjectorstringtosupportmodelattributestylepredicates
http://backbonejs.org/#changelog
14/57
3/16/2016
Backbone.js
orafunctionthatreceivesthemodelinstanceasanargument.
forEach(each)
map(collect)
reduce(foldl,inject)
reduceRight(foldr)
find(detect)
findIndex
findLastIndex
filter(select)
reject
every(all)
some(any)
contains(includes)
invoke
max
min
sortBy
groupBy
shuffle
toArray
size
first(head,take)
initial
rest(tail,drop)
last
without
indexOf
lastIndexOf
isEmpty
chain
difference
sample
partition
countBy
indexBy
books.each(function(book){
book.publish();
});
vartitles=books.map("title");
varpublishedBooks=books.filter({published:true});
varalphabetical=books.sortBy(function(book){
returnbook.author.get("name").toLowerCase();
});
varrandomThree=books.sample(3);
add
collection.add(models,[options])
http://backbonejs.org/#changelog
15/57
3/16/2016
Backbone.js
firinganyappropriate "change" events.
varships=newBackbone.Collection;
ships.on("add",function(ship){
alert("Ahoy"+ship.get("name")+"!");
});
ships.add([
{name:"FlyingDutchman"},
{name:"BlackPearl"}
]);
Notethataddingthesamemodel(amodelwiththesame id )toacollectionmorethanonce
isanoop.
remove
collection.remove(models,[options])
Removeamodel(oranarrayofmodels)fromthecollection,andreturnthem.Each
modelcanbeaModelinstance,an id stringoraJSobject,anyvalueacceptableas
the id argumentof collection.get .Firesa "remove" eventforeachmodel,anda
single "update" eventafterwards,unless {silent:true} ispassed.Themodel's
indexbeforeremovalisavailabletolistenersas options.index .
reset
collection.reset([models],[options])
Addingandremovingmodelsoneatatimeisallwellandgood,butsometimesyou
havesomanymodelstochangethatyou'dratherjustupdatethecollectioninbulk.
Useresettoreplaceacollectionwithanewlistofmodels(orattributehashes),
triggeringasingle "reset" eventoncompletion,andwithouttriggeringanyaddor
removeeventsonanymodels.Returnsthenewlysetmodels.Forconvenience,within
a "reset" event,thelistofanypreviousmodelsisavailableas
options.previousModels .
set
collection.set(models,[options])
Thesetmethodperformsa"smart"updateofthecollectionwiththepassedlistof
models.Ifamodelinthelistisn'tyetinthecollectionitwillbeaddedifthemodelis
alreadyinthecollectionitsattributeswillbemergedandifthecollectioncontainsany
modelsthataren'tpresentinthelist,they'llberemoved.Alloftheappropriate "add" ,
"remove" ,and "change" eventsarefiredasthishappens.Returnsthetouched
modelsinthecollection.Ifyou'dliketocustomizethebehavior,youcandisableitwith
options: {add:false} , {remove:false} ,or {merge:false} .
varvanHalen=newBackbone.Collection([eddie,alex,stone,roth]);
vanHalen.set([eddie,alex,stone,hagar]);
//Firesa"remove"eventforroth,andan"add"eventfor"hagar".
//Updatesanyofstone,alex,andeddie'sattributesthatmayhave
//changedovertheyears.
get
collection.get(id)
Getamodelfromacollection,specifiedbyanid,acid,orbypassinginamodel.
varbook=library.get(110);
http://backbonejs.org/#changelog
16/57
3/16/2016
Backbone.js
at
collection.at(index)
Getamodelfromacollection,specifiedbyindex.Usefulifyourcollectionissorted,
andifyourcollectionisn'tsorted,atwillstillretrievemodelsininsertionorder.When
passedanegativeindex,itwillretrievethemodelfromthebackofthecollection.
push
collection.push(model,[options])
Addamodelattheendofacollection.Takesthesameoptionsasadd.
pop
collection.pop([options])
Removeandreturnthelastmodelfromacollection.Takesthesameoptionsas
remove.
unshift
collection.unshift(model,[options])
Addamodelatthebeginningofacollection.Takesthesameoptionsasadd.
shift
collection.shift([options])
Removeandreturnthefirstmodelfromacollection.Takesthesameoptionsas
remove.
slice
collection.slice(begin,end)
Returnashallowcopyofthiscollection'smodels,usingthesameoptionsasnative
Array#slice.
length
collection.length
comparator
collection.comparator
Bydefaultthereisnocomparatorforacollection.Ifyoudefineacomparator,itwillbe
usedtomaintainthecollectioninsortedorder.Thismeansthatasmodelsareadded,
theyareinsertedatthecorrectindexin collection.models .Acomparatorcanbe
definedasasortBy(passafunctionthattakesasingleargument),asasort(passa
comparatorfunctionthatexpectstwoarguments),orasastringindicatingtheattribute
tosortby.
"sortBy"comparatorfunctionstakeamodelandreturnanumericorstringvalueby
whichthemodelshouldbeorderedrelativetoothers."sort"comparatorfunctionstake
twomodels,andreturn 1 ifthefirstmodelshouldcomebeforethesecond, 0 ifthey
areofthesamerankand 1 ifthefirstmodelshouldcomeafter.NotethatBackbone
dependsonthearityofyourcomparatorfunctiontodeterminebetweenthetwostyles,
sobecarefulifyourcomparatorfunctionisbound.
Notehoweventhoughallofthechaptersinthisexampleareaddedbackwards,they
comeoutintheproperorder:
varChapter=Backbone.Model;
varchapters=newBackbone.Collection;
chapters.comparator='page';
chapters.add(newChapter({page:9,title:"TheEnd"}));
chapters.add(newChapter({page:5,title:"TheMiddle"}));
chapters.add(newChapter({page:1,title:"TheBeginning"}));
alert(chapters.pluck('title'));
Collectionswithacomparatorwillnotautomaticallyresortifyoulaterchangemodelattributes,soyou
maywishtocall sort afterchangingmodelattributesthatwouldaffecttheorder.
sort
collection.sort([options])
Forceacollectiontoresortitself.Youdon'tneedtocallthisundernormal
http://backbonejs.org/#changelog
17/57
3/16/2016
Backbone.js
circumstances,asacollectionwithacomparatorwillsortitselfwheneveramodelis
added.Todisablesortingwhenaddingamodel,pass {sort:false} to add .Calling
sorttriggersa "sort" eventonthecollection.
pluck
collection.pluck(attribute)
where
collection.where(attributes)
Returnanarrayofallthemodelsinacollectionthatmatchthepassedattributes.
Usefulforsimplecasesof filter .
varfriends=newBackbone.Collection([
{name:"Athos",job:"Musketeer"},
{name:"Porthos",job:"Musketeer"},
{name:"Aramis",job:"Musketeer"},
{name:"d'Artagnan",job:"Guard"},
]);
varmusketeers=friends.where({job:"Musketeer"});
alert(musketeers.length);
findWhere
collection.findWhere(attributes)
Justlikewhere,butdirectlyreturnsonlythefirstmodelinthecollectionthatmatches
thepassedattributes.
url
collection.urlorcollection.url()
Settheurlproperty(orfunction)onacollectiontoreferenceitslocationontheserver.
ModelswithinthecollectionwilluseurltoconstructURLsoftheirown.
varNotes=Backbone.Collection.extend({
url:'/notes'
});
//Or,somethingmoresophisticated:
varNotes=Backbone.Collection.extend({
url:function(){
returnthis.document.url()+'/notes';
}
});
parse
collection.parse(response,options)
parseiscalledbyBackbonewheneveracollection'smodelsarereturnedbythe
server,infetch.Thefunctionispassedtheraw response object,andshouldreturnthe
arrayofmodelattributestobeaddedtothecollection.Thedefaultimplementationisa
noop,simplypassingthroughtheJSONresponse.Overridethisifyouneedtowork
withapreexistingAPI,orbetternamespaceyourresponses.
varTweets=Backbone.Collection.extend({
//TheTwitterSearchAPIreturnstweetsunder"results".
parse:function(response){
returnresponse.results;
}
});
http://backbonejs.org/#changelog
18/57
3/16/2016
Backbone.js
clone
collection.clone()
Returnsanewinstanceofthecollectionwithanidenticallistofmodels.
fetch
collection.fetch([options])
Fetchthedefaultsetofmodelsforthiscollectionfromtheserver,settingthemonthe
collectionwhentheyarrive.Theoptionshashtakes success and error callbacks
whichwillbothbepassed (collection,response,options) asarguments.Whenthe
modeldatareturnsfromtheserver,itusessetto(intelligently)mergethefetched
models,unlessyoupass {reset:true} ,inwhichcasethecollectionwillbe(efficiently)
reset.DelegatestoBackbone.syncunderthecoversforcustompersistencestrategies
andreturnsajqXHR.TheserverhandlerforfetchrequestsshouldreturnaJSON
arrayofmodels.
Backbone.sync=function(method,model){
alert(method+":"+model.url);
};
varaccounts=newBackbone.Collection;
accounts.url='/accounts';
accounts.fetch();
Thebehavioroffetchcanbecustomizedbyusingtheavailablesetoptions.For
example,tofetchacollection,gettingan "add" eventforeverynewmodel,anda
"change" eventforeverychangedexistingmodel,withoutremovinganything:
collection.fetch({remove:false})
jQuery.ajaxoptionscanalsobepasseddirectlyasfetchoptions,sotofetchaspecific
pageofapaginatedcollection: Documents.fetch({data:{page:3}})
Notethatfetchshouldnotbeusedtopopulatecollectionsonpageloadallmodels
neededatloadtimeshouldalreadybebootstrappedintoplace.fetchisintendedfor
lazilyloadingmodelsforinterfacesthatarenotneededimmediately:forexample,
documentswithcollectionsofnotesthatmaybetoggledopenandclosed.
create
collection.create(attributes,[options])
Conveniencetocreateanewinstanceofamodelwithinacollection.Equivalentto
instantiatingamodelwithahashofattributes,savingthemodeltotheserver,and
addingthemodeltothesetafterbeingsuccessfullycreated.Returnsthenewmodel.If
clientsidevalidationfailed,themodelwillbeunsaved,withvalidationerrors.Inorder
forthistowork,youshouldsetthemodelpropertyofthecollection.Thecreate
methodcanaccepteitheranattributeshashoranexisting,unsavedmodelobject.
Creatingamodelwillcauseanimmediate "add" eventtobetriggeredonthe
collection,a "request" eventasthenewmodelissenttotheserver,aswellasa
"sync" event,oncetheserverhasrespondedwiththesuccessfulcreationofthe
Backbone.Router
Webapplicationsoftenprovidelinkable,bookmarkable,shareableURLsforimportant
locationsintheapp.Untilrecently,hashfragments( #page )wereusedtoprovidethese
permalinks,butwiththearrivaloftheHistoryAPI,it'snowpossibletousestandard
http://backbonejs.org/#changelog
19/57
3/16/2016
Backbone.js
URLs( /page ).Backbone.Routerprovidesmethodsforroutingclientsidepages,and
connectingthemtoactionsandevents.Forbrowserswhichdon'tyetsupportthe
HistoryAPI,theRouterhandlesgracefulfallbackandtransparenttranslationtothe
fragmentversionoftheURL.
Duringpageload,afteryourapplicationhasfinishedcreatingallofitsrouters,besure
tocall Backbone.history.start() or Backbone.history.start({pushState:true}) to
routetheinitialURL.
extend
Backbone.Router.extend(properties,[classProperties])
Getstartedbycreatingacustomrouterclass.Defineactionsthataretriggeredwhen
certainURLfragmentsarematched,andprovidearouteshashthatpairsroutesto
actions.Notethatyou'llwanttoavoidusingaleadingslashinyourroutedefinitions:
varWorkspace=Backbone.Router.extend({
routes:{
"help":"help",//#help
"search/:query":"search",//#search/kiwis
"search/:query/p:page":"search"//#search/kiwis/p7
},
help:function(){
...
},
search:function(query,page){
...
}
});
routes
router.routes
TherouteshashmapsURLswithparameterstofunctionsonyourrouter(orjustdirect
functiondefinitions,ifyouprefer),similartotheView'seventshash.Routescan
containparameterparts, :param ,whichmatchasingleURLcomponentbetween
slashesandsplatparts *splat ,whichcanmatchanynumberofURLcomponents.
Partofaroutecanbemadeoptionalbysurroundingitinparentheses (/:optional) .
Forexample,arouteof "search/:query/p:page" willmatchafragmentof
#search/obama/p2 ,passing "obama" and "2" totheaction.
http://backbonejs.org/#changelog
20/57
3/16/2016
Backbone.js
"folder/:name:mode":"openFolder"
}
router.on("route:help",function(page){
...
});
constructor/initialize
newRouter([options])
Whencreatinganewrouter,youmaypassitsrouteshashdirectlyasanoption,ifyou
choose.All options willalsobepassedtoyour initialize function,ifdefined.
route
router.route(route,name,[callback])
navigate
router.navigate(fragment,[options])
Wheneveryoureachapointinyourapplicationthatyou'dliketosaveasaURL,call
navigateinordertoupdatetheURL.Ifyoualsowishtocalltheroutefunction,setthe
triggeroptionto true .ToupdatetheURLwithoutcreatinganentryinthebrowser's
history,setthereplaceoptionto true .
openPage:function(pageNumber){
this.document.pages.at(pageNumber).open();
this.navigate("page/"+pageNumber);
}
#Or...
app.navigate("help/troubleshooting",{trigger:true});
#Or...
app.navigate("help/troubleshooting",{trigger:true,replace:true});
execute
router.execute(callback,args,name)
Thismethodiscalledinternallywithintherouter,wheneveraroutematchesandits
correspondingcallbackisabouttobeexecuted.Returnfalsefromexecutetocancel
thecurrenttransition.Overrideittoperformcustomparsingorwrappingofyour
routes,forexample,toparsequerystringsbeforehandingthemtoyourroutecallback,
likeso:
varRouter=Backbone.Router.extend({
execute:function(callback,args,name){
if(!loggedIn){
goToLogin();
returnfalse;
}
args.push(parseQueryString(args.pop()));
if(callback)callback.apply(this,args);
}
});
http://backbonejs.org/#changelog
21/57
3/16/2016
Backbone.js
Backbone.history
Historyservesasaglobalrouter(perframe)tohandle hashchange eventsor
pushState ,matchtheappropriateroute,andtriggercallbacks.Youshouldn'tever
start
Backbone.history.start([options])
WhenallofyourRoutershavebeencreated,andalloftheroutesaresetupproperly,
call Backbone.history.start() tobeginmonitoring hashchange events,anddispatching
routes.Subsequentcallsto Backbone.history.start() willthrowanerror,and
Backbone.History.started isabooleanvalueindicatingwhetherithasalreadybeen
called.
Toindicatethatyou'dliketouseHTML5 pushState supportinyourapplication,use
Backbone.history.start({pushState:true}) .Ifyou'dliketouse pushState ,buthave
browsersthatdon'tsupportitnativelyusefullpagerefreshesinstead,youcanadd
{hashChange:false} totheoptions.
Ifyourapplicationisnotbeingservedfromtherooturl / ofyourdomain,besureto
tellHistorywheretherootreallyis,asanoption: Backbone.history.start({pushState:
true,root:"/public/search/"})
Whencalled,ifaroutesucceedswithamatchforthecurrentURL,
Backbone.history.start() returns true .IfnodefinedroutematchesthecurrentURL,
itreturns false .
Iftheserverhasalreadyrenderedtheentirepage,andyoudon'twanttheinitialroute
totriggerwhenstartingHistory,pass silent:true .
BecausehashbasedhistoryinInternetExplorerreliesonan <iframe> ,besuretocall
start() onlyaftertheDOMisready.
$(function(){
newWorkspaceRouter();
newHelpPaneRouter();
Backbone.history.start({pushState:true});
});
Backbone.sync
Backbone.syncisthefunctionthatBackbonecallseverytimeitattemptstoreador
saveamodeltotheserver.Bydefault,ituses jQuery.ajax tomakeaRESTfulJSON
requestandreturnsajqXHR.Youcanoverrideitinordertouseadifferentpersistence
strategy,suchasWebSockets,XMLtransport,orLocalStorage.
ThemethodsignatureofBackbone.syncis sync(method,model,[options])
methodtheCRUDmethod( "create" , "read" , "update" ,or "delete" )
modelthemodeltobesaved(orcollectiontoberead)
optionssuccessanderrorcallbacks,andallotherjQueryrequestoptions
http://backbonejs.org/#changelog
22/57
3/16/2016
Backbone.js
Withthedefaultimplementation,whenBackbone.syncsendsuparequesttosavea
model,itsattributeswillbepassed,serializedasJSON,andsentintheHTTPbody
withcontenttype application/json .WhenreturningaJSONresponse,senddownthe
attributesofthemodelthathavebeenchangedbytheserver,andneedtobeupdated
ontheclient.Whenrespondingtoa "read" requestfromacollection
(Collection#fetch),senddownanarrayofmodelattributeobjects.
Wheneveramodelorcollectionbeginsasyncwiththeserver,a "request" eventis
emitted.Iftherequestcompletessuccessfullyyou'llgeta "sync" event,andan
"error" eventifnot.
OnemoretipforintegratingRailsversionspriorto3.1istodisablethedefault
namespacingfor to_json callsonmodelsbysetting
ActiveRecord::Base.include_root_in_json=false
ajax
Backbone.ajax=function(request){...};
IfyouwanttouseacustomAJAXfunction,oryourendpointdoesn'tsupportthe
jQuery.ajaxAPIandyouneedtotweakthings,youcandosobysetting
Backbone.ajax .
emulateHTTP
Backbone.emulateHTTP=true
Ifyouwanttoworkwithalegacywebserverthatdoesn'tsupportBackbone'sdefault
REST/HTTPapproach,youmaychoosetoturnon Backbone.emulateHTTP .Settingthis
optionwillfake PUT , PATCH and DELETE requestswithaHTTP POST ,settingthe X
HTTPMethodOverride headerwiththetruemethod.If emulateJSON isalsoon,thetrue
emulateJSON
Backbone.emulateJSON=true
Ifyou'reworkingwithalegacywebserverthatcan'thandlerequestsencodedas
application/json ,setting Backbone.emulateJSON=true; willcausetheJSONtobe
Backbone.View
Backboneviewsarealmostmoreconventionthantheyarecodetheydon't
determineanythingaboutyourHTMLorCSSforyou,andcanbeusedwithany
http://backbonejs.org/#changelog
23/57
3/16/2016
Backbone.js
JavaScripttemplatinglibrary.Thegeneralideaistoorganizeyourinterfaceintological
views,backedbymodels,eachofwhichcanbeupdatedindependentlywhenthe
modelchanges,withouthavingtoredrawthepage.InsteadofdiggingintoaJSON
object,lookingupanelementintheDOM,andupdatingtheHTMLbyhand,youcan
bindyourview's render functiontothemodel's "change" eventandnow
everywherethatmodeldataisdisplayedintheUI,itisalwaysimmediatelyuptodate.
extend
Backbone.View.extend(properties,[classProperties])
Getstartedwithviewsbycreatingacustomviewclass.You'llwanttooverridethe
renderfunction,specifyyourdeclarativeevents,andperhapsthe tagName , className ,
or id oftheView'srootelement.
varDocumentRow=Backbone.View.extend({
tagName:"li",
className:"documentrow",
events:{
"click.icon":"open",
"click.button.edit":"openEditDialog",
"click.button.delete":"destroy"
},
initialize:function(){
this.listenTo(this.model,"change",this.render);
},
render:function(){
...
}
});
constructor/initialize
newView([options])
Thereareseveralspecialoptionsthat,ifpassed,willbeattacheddirectlytotheview:
model , collection , el , id , className , tagName , attributes and events .Ifthe
viewdefinesaninitializefunction,itwillbecalledwhentheviewisfirstcreated.If
you'dliketocreateaviewthatreferencesanelementalreadyintheDOM,passinthe
elementasanoption: newView({el:existingElement})
vardoc=documents.first();
newDocumentRow({
model:doc,
id:"documentrow"+doc.id
});
el
view.el
AllviewshaveaDOMelementatalltimes(theelproperty),whetherthey'vealready
beeninsertedintothepageornot.Inthisfashion,viewscanberenderedatanytime,
andinsertedintotheDOMallatonce,inordertogethighperformanceUIrendering
withasfewreflowsandrepaintsaspossible.
this.el canberesolvedfromaDOMselectorstringoranElementotherwiseitwill
http://backbonejs.org/#changelog
24/57
3/16/2016
Backbone.js
varitem=newItemView();
varbody=newBodyView();
alert(item.el+''+body.el);
$el
view.$el
AcachedjQueryobjectfortheview'selement.Ahandyreferenceinsteadofre
wrappingtheDOMelementallthetime.
view.$el.show();
listView.$el.append(itemView.el);
setElement
view.setElement(element)
Ifyou'dliketoapplyaBackboneviewtoadifferentDOMelement,usesetElement,
whichwillalsocreatethecached $el referenceandmovetheview'sdelegatedevents
fromtheoldelementtothenewone.
attributes
view.attributes
AhashofattributesthatwillbesetasHTMLDOMelementattributesontheview's el
(id,class,dataproperties,etc.),orafunctionthatreturnssuchahash.
$(jQuery)
view.$(selector)
IfjQueryisincludedonthepage,eachviewhasa$functionthatrunsqueriesscoped
withintheview'selement.IfyouusethisscopedjQueryfunction,youdon'thavetouse
modelidsaspartofyourquerytopulloutspecificelementsinalist,andcanrelymuch
moreonHTMLclassattributes.It'sequivalenttorunning: view.$el.find(selector)
ui.Chapter=Backbone.View.extend({
serialize:function(){
return{
title:this.$(".title").text(),
start:this.$(".startpage").text(),
end:this.$(".endpage").text()
};
}
});
template
view.template([data])
Whiletemplatingforaviewisn'tafunctionprovideddirectlybyBackbone,it'softena
niceconventiontodefineatemplatefunctiononyourviews.Inthisway,when
renderingyourview,youhaveconvenientaccesstoinstancedata.Forexample,using
Underscoretemplates:
varLibraryView=Backbone.View.extend({
template:_.template(...)
});
render
view.render()
Thedefaultimplementationofrenderisanoop.Overridethisfunctionwithyourcode
thatrenderstheviewtemplatefrommodeldata,andupdates this.el withthenew
HTML.Agoodconventionisto returnthis attheendofrendertoenablechained
calls.
varBookmark=Backbone.View.extend({
template:_.template(...),
render:function(){
this.$el.html(this.template(this.model.attributes));
returnthis;
}
});
BackboneisagnosticwithrespecttoyourpreferredmethodofHTMLtemplating.Your
renderfunctioncouldevenmungetogetheranHTMLstring,oruse
http://backbonejs.org/#changelog
25/57
3/16/2016
Backbone.js
document.createElement togenerateaDOMtree.However,wesuggestchoosinga
niceJavaScripttemplatinglibrary.Mustache.js,Hamljs,andEcoareallfine
alternatives.BecauseUnderscore.jsisalreadyonthepage,_.templateisavailable,
andisanexcellentchoiceifyouprefersimpleinterpolatedJavaScriptstyletemplates.
Whatevertemplatingstrategyyouendupwith,it'sniceifyouneverhavetoputstrings
ofHTMLinyourJavaScript.AtDocumentCloud,weuseJammitinordertopackageup
JavaScripttemplatesstoredin /app/views aspartofourmain core.js asset
package.
remove
view.remove()
Removesaviewandits el fromtheDOM,andcallsstopListeningtoremoveany
boundeventsthattheviewhaslistenTo'd.
events
view.eventsorview.events()
Theeventshash(ormethod)canbeusedtospecifyasetofDOMeventsthatwillbe
boundtomethodsonyourViewthroughdelegateEvents.
Backbonewillautomaticallyattachtheeventlistenersatinstantiationtime,rightbefore
invokinginitialize.
varENTER_KEY=13;
varInputView=Backbone.View.extend({
tagName:'input',
events:{
"keydown":"keyAction",
},
render:function(){...},
keyAction:function(e){
if(e.which===ENTER_KEY){
this.collection.add({text:this.$el.val()});
}
}
});
delegateEvents
delegateEvents([events])
UsesjQuery's on functiontoprovidedeclarativecallbacksforDOMeventswithina
view.Ifaneventshashisnotpasseddirectly,uses this.events asthesource.Events
arewrittenintheformat {"eventselector":"callback"} .Thecallbackmaybeeither
thenameofamethodontheview,oradirectfunctionbody.Omittingthe selector
causestheeventtobeboundtotheview'srootelement( this.el ).Bydefault,
delegateEvents iscalledwithintheView'sconstructorforyou,soifyouhaveasimple
events hash,allofyourDOMeventswillalwaysalreadybeconnected,andyouwill
neverhavetocallthisfunctionyourself.
The events propertymayalsobedefinedasafunctionthatreturnsaneventshash,
tomakeiteasiertoprogrammaticallydefineyourevents,aswellasinheritthemfrom
parentviews.
UsingdelegateEventsprovidesanumberofadvantagesovermanuallyusingjQuery
tobindeventstochildelementsduringrender.Allattachedcallbacksareboundtothe
viewbeforebeinghandedofftojQuery,sowhenthecallbacksareinvoked, this
continuestorefertotheviewobject.WhendelegateEventsisrunagain,perhapswith
adifferent events hash,allcallbacksareremovedanddelegatedafreshusefulfor
viewswhichneedtobehavedifferentlywhenindifferentmodes.
AsingleeventversionofdelegateEventsisavailableas delegate .Infact,
delegateEventsissimplyamultieventwrapperaround delegate .Acounterpartto
undelegateEvents isavailableas undelegate .
Aviewthatdisplaysadocumentinasearchresultmightlooksomethinglikethis:
http://backbonejs.org/#changelog
26/57
3/16/2016
Backbone.js
varDocumentView=Backbone.View.extend({
events:{
"dblclick":"open",
"click.icon.doc":"select",
"contextmenu.icon.doc":"showMenu",
"click.show_notes":"toggleNotes",
"click.title.lock":"editAccessLevel",
"mouseover.title.date":"showTooltip"
},
render:function(){
this.$el.html(this.template(this.model.attributes));
returnthis;
},
open:function(){
window.open(this.model.get("viewer_url"));
},
select:function(){
this.model.set({selected:true});
},
...
});
undelegateEvents
undelegateEvents()
Removesalloftheview'sdelegatedevents.Usefulifyouwanttodisableorremovea
viewfromtheDOMtemporarily.
Utility
Backbone.noConflict
varbackbone=Backbone.noConflict();
Backboneonthirdpartywebsites,whereyoudon'twanttoclobbertheexisting
Backbone.
varlocalBackbone=Backbone.noConflict();
varmodel=localBackbone.Model.extend(...);
Backbone.$
Backbone.$=$;
F.A.Q.
WhyuseBackbone,not[otherframeworkX]?
Ifyoureyehasn'talreadybeencaughtbytheadaptabilityandelanondisplayinthe
abovelistofexamples,wecangetmorespecific:Backbone.jsaimstoprovidethe
commonfoundationthatdatarichwebapplicationswithambitiousinterfacesrequire
whileverydeliberatelyavoidingpaintingyouintoacornerbymakinganydecisionsthat
you'rebetterequippedtomakeyourself.
Thefocusisonsupplyingyouwithhelpfulmethodstomanipulateandqueryyourdata,noton
HTMLwidgetsorreinventingtheJavaScriptobjectmodel.
Backbonedoesnotforceyoutouseasingletemplateengine.ViewscanbindtoHTML
constructedinyourfavoriteway.
It'ssmaller.Therearefewerkilobytesforyourbrowserorphonetodownload,andless
conceptualsurfacearea.Youcanreadandunderstandthesourceinanafternoon.
Itdoesn'tdependonstuffingapplicationlogicintoyourHTML.There'snoembedded
JavaScript,templatelogic,orbindinghookupcodein data or ng attributes,andnoneed
http://backbonejs.org/#changelog
27/57
3/16/2016
Backbone.js
toinventyourownHTMLtags.
Synchronouseventsareusedasthefundamentalbuildingblock,notadifficulttoreasonabout
runloop,orbyconstantlypollingandtraversingyourdatastructurestohuntforchanges.And
ifyouwantaspecificeventtobeasynchronousandaggregated,noproblem.
Backbonescaleswell,fromembeddedwidgetstomassiveapps.
Backboneisalibrary,notaframework,andplayswellwithothers.YoucanembedBackbone
widgetsinDojoappswithouttrouble,oruseBackbonemodelsasthedatabackingforD3
visualizations(topicktwoentirelyrandomexamples).
"Twowaydatabinding"isavoided.Whileitcertainlymakesforaniftydemo,andworksforthe
mostbasicCRUD,itdoesn'ttendtobeterriblyusefulinyourrealworldapp.Sometimesyou
wanttoupdateoneverykeypress,sometimesonblur,sometimeswhenthepanelisclosed,
andsometimeswhenthe"save"buttonisclicked.Inalmostallcases,simplyserializingthe
formtoJSONisfasterandeasier.Allthataside,ifyourheartisset,goforit.
There'snobuiltinperformancepenaltyforchoosingtostructureyourcodewithBackbone.And
ifyoudowanttooptimizefurther,thinmodelsandtemplateswithflexiblegranularitymakeit
easytosqueezeeverylastdropofpotentialperformanceoutof,say,IE8.
There'sMoreThanOneWayToDoIt
It'scommonforfolksjustgettingstartedtotreattheexampleslistedonthispageas
somesortofgospeltruth.Infact,Backbone.jsisintendedtobefairlyagnosticabout
manycommonpatternsinclientsidecode.Forexample...
ReferencesbetweenModelsandViewscanbehandledseveralways.Somepeople
liketohavedirectpointers,whereviewscorrespond1:1withmodels( model.view and
view.model ).Othersprefertohaveintermediate"controller"objectsthatorchestrate
thecreationandorganizationofviewsintoahierarchy.Othersstillprefertheevented
approach,andalwaysfireeventsinsteadofcallingmethodsdirectly.Allofthesestyles
workwell.
BatchoperationsonModelsarecommon,butoftenbesthandleddifferently
dependingonyourserversidesetup.Somefolksdon'tmindmakingindividualAjax
requests.OtherscreateexplicitresourcesforRESTfulbatchoperations:
/notes/batch/destroy?ids=1,2,3,4 .OtherstunnelRESToverJSON,withthecreation
of"changeset"requests:
{
"create":[arrayofmodelstocreate]
"update":[arrayofmodelstoupdate]
"destroy":[arrayofmodelidstodestroy]
}
Feelfreetodefineyourownevents.Backbone.Eventsisdesignedsothatyoucan
mixitintoanyJavaScriptobjectorprototype.Sinceyoucanuseanystringasan
event,it'softenhandytobindandtriggeryourowncustomevents:
model.on("selected:true") or model.on("editing")
RendertheUIasyouseefit.BackboneisagnosticastowhetheryouuseUnderscore
templates,Mustache.js,directDOMmanipulation,serversiderenderedsnippetsof
HTML,orjQueryUIinyour render function.Sometimesyou'llcreateaviewforeach
model...sometimesyou'llhaveaviewthatrendersthousandsofmodelsatonce,ina
tightloop.Bothcanbeappropriateinthesameapp,dependingonthequantityofdata
involved,andthecomplexityoftheUI.
NestedModels&Collections
It'scommontonestcollectionsinsideofmodelswithBackbone.Forexample,consider
a Mailbox modelthatcontainsmany Message models.Onenicepatternforhandling
thisishavea this.messages collectionforeachmailbox,enablingthelazyloadingof
messages,whenthemailboxisfirstopened...perhapswith MessageList views
listeningfor "add" and "remove" events.
varMailbox=Backbone.Model.extend({
initialize:function(){
this.messages=newMessages;
this.messages.url='/mailbox/'+this.id+'/messages';
this.messages.on("reset",this.updateCounts);
http://backbonejs.org/#changelog
28/57
3/16/2016
Backbone.js
},
...
});
varinbox=newMailbox;
//Andthen,whentheInboxisopened:
inbox.messages.fetch({reset:true});
Ifyou'relookingforsomethingmoreopinionated,thereareanumberofBackbone
pluginsthataddsophisticatedassociationsamongmodels,availableonthewiki.
Backbonedoesn'tincludedirectsupportfornestedmodelsandcollectionsor"has
many"associationsbecausethereareanumberofgoodpatternsformodeling
structureddataontheclientside,andBackboneshouldprovidethefoundationfor
implementinganyofthem.Youmaywantto
MirroranSQLdatabase'sstructure,orthestructureofaNoSQLdatabase.
Usemodelswitharraysof"foreignkey"ids,andjointotoplevelcollections(alatables).
Forassociationsthatarenumerous,usearangeofidsinsteadofanexplicitlist.
Avoidids,andusedirectreferences,creatingapartialobjectgraphrepresentingyourdataset.
Lazilyloadjoinedmodelsfromtheserver,orlazilydeserializenestedmodelsfromJSON
documents.
LoadingBootstrappedModels
Whenyourappfirstloads,it'scommontohaveasetofinitialmodelsthatyouknow
you'regoingtoneed,inordertorenderthepage.InsteadoffiringanextraAJAX
requesttofetchthem,anicerpatternistohavetheirdataalreadybootstrappedinto
thepage.Youcanthenuseresettopopulateyourcollectionswiththeinitialdata.At
DocumentCloud,intheERBtemplatefortheworkspace,wedosomethingalongthese
lines:
<script>
varaccounts=newBackbone.Collection;
accounts.reset(<%=@accounts.to_json%>);
varprojects=newBackbone.Collection;
projects.reset(<%=@projects.to_json(:collaborators=>true)%>);
</script>
ExtendingBackbone
ManyJavaScriptlibrariesaremeanttobeinsularandselfenclosed,whereyou
interactwiththembycallingtheirpublicAPI,butneverpeekinsideattheguts.
Backbone.jsisnotthatkindoflibrary.
Becauseitservesasafoundationforyourapplication,you'remeanttoextendand
enhanceitinthewaysyouseefittheentiresourcecodeisannotatedtomakethis
easierforyou.You'llfindthatthere'sverylittlethereapartfromcorefunctions,and
mostofthosecanbeoverriddenoraugmentedshouldyoufindtheneed.Ifyoucatch
yourselfaddingmethodsto Backbone.Model.prototype ,orcreatingyourownbase
subclass,don'tworrythat'showthingsaresupposedtowork.
HowdoesBackbonerelateto"traditional"MVC?
DifferentimplementationsoftheModelViewControllerpatterntendtodisagreeabout
thedefinitionofacontroller.Ifithelpsany,inBackbone,theViewclasscanalsobe
thoughtofasakindofcontroller,dispatchingeventsthatoriginatefromtheUI,withthe
HTMLtemplateservingasthetrueview.WecallitaViewbecauseitrepresentsa
logicalchunkofUI,responsibleforthecontentsofasingleDOMelement.
ComparingtheoverallstructureofBackbonetoaserversideMVCframeworklike
Rails,thepieceslineuplikeso:
http://backbonejs.org/#changelog
29/57
3/16/2016
Backbone.js
Backbone.ModelLikeaRailsmodelminustheclassmethods.Wrapsarowofdatain
businesslogic.
Backbone.CollectionAgroupofmodelsontheclientside,withsorting/filtering/aggregation
logic.
Backbone.RouterRails routes.rb +Railscontrolleractions.MapsURLstofunctions.
Backbone.ViewAlogical,reusablepieceofUI.Often,butnotalways,associatedwitha
model.
ClientsideTemplatesRails .html.erb views,renderingachunkofHTML.
Binding"this"
PerhapsthesinglemostcommonJavaScript"gotcha"isthefactthatwhenyoupassa
functionasacallback,itsvaluefor this islost.Whendealingwitheventsand
callbacksinBackbone,you'lloftenfinditusefultorelyonlistenToortheoptional
context argumentthatmanyofUnderscoreandBackbone'smethodsusetospecify
WorkingwithRails
Backbone.jswasoriginallyextractedfromaRailsapplicationgettingyourclientside
(Backbone)Modelstosynccorrectlywithyourserverside(Rails)Modelsispainless,
buttherearestillafewthingstobeawareof.
Bydefault,Railsversionspriorto3.1addanextralayerofwrappingaroundtheJSON
representationofmodels.Youcandisablethiswrappingbysetting:
ActiveRecord::Base.include_root_in_json=false
...inyourconfiguration.Otherwise,overrideparsetopullmodelattributesoutofthe
wrapper.Similarly,BackbonePUTsandPOSTsdirectJSONrepresentationsofmodels,
wherebydefaultRailsexpectsnamespacedattributes.Youcanhaveyourcontrollers
filterattributesdirectlyfrom params ,oryoucanoverridetoJSONinBackbonetoadd
theextrawrappingRailsexpects.
Examples
Thelistofexamplesthatfollows,whilelong,isnotexhaustive.Ifyou'veworkedonan
appthatusesBackbone,pleaseaddittothewikipageofBackboneapps.
JrmeGravelNiquethascontributedaTodoListapplicationthatisbundledinthe
repositoryasBackboneexample.Ifyou'rewonderingwheretogetstartedwith
Backboneingeneral,takeamomenttoreadthroughtheannotatedsource.Theapp
usesaLocalStorageadaptertotransparentlysaveallofyourtodoswithinyour
browser,insteadofsendingthemtoaserver.Jrmealsohasaversionhostedat
localtodos.com.
http://backbonejs.org/#changelog
30/57