Last active
August 29, 2015 14:14
-
-
Save hiasinho/7d35cd6929160fa7d7de to your computer and use it in GitHub Desktop.
React mixin for integrating Backbone
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Backbone.React = {} unless Backbone.React | |
Backbone.React.Base = {} unless Backbone.React.Base | |
### | |
Backbone React Base Mixin | |
========================= | |
Usage example: | |
-------------- | |
var ContactCard = React.createClass({ | |
mixins: [Backbone.React.Base.mixin], | |
render: function() { | |
return ( | |
<div> | |
<h1>{@model.get('name')}</h1> | |
</div> | |
); | |
} | |
}); | |
var person = new Backbone.Model({name: 'Zlatan'}) | |
React.render(<ContactCard model={person} />, document.body); | |
### | |
Backbone.React.Base.mixin = | |
componentWillMount: -> | |
if @props.fetch && @props.fetch != false | |
@setAndFetch(@props.collection, @props.fetch) | |
else | |
@setCollection(@props.collection) if _.has @props, 'collection' | |
@setModel(@props.model) if _.has @props, 'model' | |
setAndFetch: (object, options = {})-> | |
if object instanceof Backbone.Model | |
object = @setModel object | |
else if object instanceof Backbone.Collection | |
object = @setCollection object | |
else | |
return false | |
if _.isBoolean options | |
object.fetch() | |
else | |
object.fetch(options) | |
setCollection: (collection, fetch = false, options = {}) -> | |
@collection = collection | |
@props = _.omit @props, 'collection' | |
@collection.on 'sync', @collectionDidSync | |
@collection | |
setModel: (model, fetch = false) -> | |
@model = model | |
@props = _.omit @props, 'model' | |
@model.on 'change', @modelDidChange | |
@model | |
collectionDidSync: (e, model) -> @forceUpdate() | |
modelDidChange: (e, model) -> @forceUpdate() | |
### | |
Backbone React Connect | |
====================== | |
Usage example: | |
-------------- | |
var User = Backbone.Model.extend(); | |
var Users = Backbone.Collection.extend({ | |
baseUrl: "http://jsonplaceholder.typicode.com/users", | |
model: User | |
}); | |
var ContactList = React.createClass({ | |
mixins: [Backbone.React.connect(Users, true)], | |
render: function() { | |
return ( | |
<ul>{@collection.map(this.renderUser)}</ul> | |
); | |
}, | |
renderUser: function(user) { | |
<li>{user.get('email')}</li> | |
} | |
}); | |
React.render(<ContactList />, document.body); | |
### | |
Backbone.React.connect = (klass, fetchOrData = false) -> | |
setProps = | |
componentWillMount: -> | |
instance = new klass() | |
@props.fetch = fetchOrData | |
@props.collection = new klass() if (instance instanceof Backbone.Collection) | |
@props.model = new klass() if (instance instanceof Backbone.Model) | |
{ mixins: [setProps, Backbone.React.Base.mixin] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
if (!Backbone.React) { | |
Backbone.React = {}; | |
} | |
if (!Backbone.React.Base) { | |
Backbone.React.Base = {}; | |
} | |
/* | |
Backbone React Base Mixin | |
========================= | |
Usage example: | |
-------------- | |
var ContactCard = React.createClass({ | |
mixins: [Backbone.React.Base.mixin], | |
render: function() { | |
return ( | |
<div> | |
<h1>{@model.get('name')}</h1> | |
</div> | |
); | |
} | |
}); | |
var person = new Backbone.Model({name: 'Zlatan'}) | |
React.render(<ContactCard model={person} />, document.body); | |
*/ | |
Backbone.React.Base.mixin = { | |
componentWillMount: function() { | |
if (this.props.fetch && this.props.fetch !== false) { | |
return this.setAndFetch(this.props.collection, this.props.fetch); | |
} else { | |
if (_.has(this.props, 'collection')) { | |
this.setCollection(this.props.collection); | |
} | |
if (_.has(this.props, 'model')) { | |
return this.setModel(this.props.model); | |
} | |
} | |
}, | |
setAndFetch: function(object, options) { | |
if (options == null) { | |
options = {}; | |
} | |
if (object instanceof Backbone.Model) { | |
object = this.setModel(object); | |
} else if (object instanceof Backbone.Collection) { | |
object = this.setCollection(object); | |
} else { | |
return false; | |
} | |
if (_.isBoolean(options)) { | |
return object.fetch(); | |
} else { | |
return object.fetch(options); | |
} | |
}, | |
setCollection: function(collection, fetch, options) { | |
if (fetch == null) { | |
fetch = false; | |
} | |
if (options == null) { | |
options = {}; | |
} | |
this.collection = collection; | |
this.props = _.omit(this.props, 'collection'); | |
this.collection.on('sync', this.collectionDidSync); | |
return this.collection; | |
}, | |
setModel: function(model, fetch) { | |
if (fetch == null) { | |
fetch = false; | |
} | |
this.model = model; | |
this.props = _.omit(this.props, 'model'); | |
this.model.on('change', this.modelDidChange); | |
return this.model; | |
}, | |
collectionDidSync: function(e, model) { | |
return this.forceUpdate(); | |
}, | |
modelDidChange: function(e, model) { | |
return this.forceUpdate(); | |
} | |
}; | |
/* | |
Backbone React Connect | |
====================== | |
Usage example: | |
-------------- | |
var User = Backbone.Model.extend(); | |
var Users = Backbone.Collection.extend({ | |
baseUrl: "http://jsonplaceholder.typicode.com/users", | |
model: User | |
}); | |
var ContactList = React.createClass({ | |
mixins: [Backbone.React.connect(Users, true)], | |
render: function() { | |
return ( | |
<ul>{@collection.map(this.renderUser)}</ul> | |
); | |
}, | |
renderUser: function(user) { | |
<li>{user.get('email')}</li> | |
} | |
}); | |
React.render(<ContactList />, document.body); | |
*/ | |
Backbone.React.connect = function(klass, fetchOrData) { | |
var setProps; | |
if (fetchOrData == null) { | |
fetchOrData = false; | |
} | |
setProps = { | |
componentWillMount: function() { | |
var instance; | |
instance = new klass(); | |
this.props.fetch = fetchOrData; | |
if (instance instanceof Backbone.Collection) { | |
this.props.collection = new klass(); | |
} | |
if (instance instanceof Backbone.Model) { | |
return this.props.model = new klass(); | |
} | |
} | |
}; | |
return { | |
mixins: [setProps, Backbone.React.Base.mixin] | |
}; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
################################################################### | |
# Models and Collections | |
################################################################### | |
Models = {} | |
Models.Post = Backbone.Model.extend | |
urlRoot: "http://jsonplaceholder.typicode.com/posts" | |
Models.PostCollection = Backbone.Collection.extend | |
url: 'http://jsonplaceholder.typicode.com/posts' | |
model: Models.Post | |
################################################################### | |
# React Components | |
################################################################### | |
Components = {} | |
Components.PostList = React.createClass | |
mixins: [Backbone.React.connect(Models.PostCollection, true)] | |
render: -> | |
if @collection | |
<div> | |
<h1>Posts</h1> | |
<p>Got {@collection.length} posts</p> | |
<button onClick={@loadData}>Load Data!</button> | |
{@collection.map(@renderPost)} | |
</div> | |
else | |
<div> | |
<h1>Posts</h1> | |
<p>Got no posts</p> | |
<button onClick={@loadData}>Load Data!</button> | |
</div> | |
renderPost: (post) -> | |
<Components.Post key={post.id} model={post} /> | |
loadData: -> | |
@collection.fetch() | |
Components.Post = React.createClass | |
mixins: [Backbone.React.Base.mixin] | |
render: -> | |
<article className="post"> | |
<h2>{@model.get('title')}</h2> | |
<button onClick={@changeTitle}>Change</button> | |
<p>{@model.get('body')}</p> | |
</article> | |
changeTitle: -> | |
@model.set('title',"Random #{_.random(500)}") | |
React.render <Components.PostList />, document.getElementById('posts') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment