make your backbone application dance
DESCRIPTION
Building Backbone applications quickly became a de-facto standard, though we can’t really define it as framework but rather just as foundation to create other frameworks. If you like Backbone, you’ll fall in love with Marionette, the best application library to create large scale Javascript applications. Nicholas will explain the framework, show examples and talk about some projects like cronycle.com that have been delivered to production using Marionette.TRANSCRIPT
![Page 1: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/1.jpg)
ake your Backbone Application Dance
May 15th, 2014 — Verona
Nicholas Valbusa@squallstar
![Page 2: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/2.jpg)
I AM
Nicholas Valbusasquallstar - squallstar.it
AT
Lead JS Developercronycle.com
![Page 3: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/3.jpg)
Our challenges:
- Expand your timeline tweets into stories
- Organize and filter your stories into collections
"Cronycle is a content curation tool based on Twitter tweets and RSS feeds"
- Make it real-time, responsive, awesome
- Live search
![Page 4: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/4.jpg)
10ppl in London
- Rails+Marionette Webclient
Paid service, at the end of this speech (Yipee!!!)
- Rails API, Elasticsearch, Redis queue
- iOS Native app
![Page 5: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/5.jpg)
Always choose the right tool for the job
![Page 6: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/6.jpg)
![Page 7: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/7.jpg)
• Solid foundation/core classes
• Flexible and simple
• Great pub/sub events architecture
• Awesome Model/Collection implementationfor REST resources
• Good MV*-style code separation (p.s. it’s a MVP)
• It is not like Angular.JS
THE GOOD PARTS
![Page 8: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/8.jpg)
• It's incredibly easy to end up in a bad place
• No Application main class (some people use its router)
• Doesn’t include automatic and good ways to bind models to their views
• No “native” way to organise the pieces of your webapp into modules
• No "native" way to organize layouts (header/footer/sidebar/content/etc..)
• It is not sponsored/maintained by Google
THE BAD PARTS
![Page 9: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/9.jpg)
let me read that again,
• “Awesome Model/Collection implementationfor REST resources”
var Library = Backbone.Collection.extend({ model: Book, url: “v1/books” });
![Page 10: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/10.jpg)
for all the rest, there’s…
![Page 12: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/12.jpg)
Very similar to Backbone, just goes a few more steps.
![Page 13: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/13.jpg)
“A composite application library for Backbone that aims to simplify the construction of large scale
JavaScript applications” !
— that sits on top of Backbone
An event-driven collection of common design and implementation patterns.
Basically… Marionette brings an application architecture to Backbone
![Page 14: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/14.jpg)
Key features
• Organised as hellApplications are built in modules, and with event-driven architecture
• No zombies Built-in memory management and zombie-killing in views, regions and layouts
• Flexible Just code the way you prefer, and picks only the features you need.
• Takes care of the rendering process
![Page 15: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/15.jpg)
TAKES CARE OF THE RENDERING
PROCESS
![Page 16: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/16.jpg)
Depends on:
Backbone & Underscore
Backbone.BabySitter & Backbone.Wreqr (both included)
just 31kb !
![Page 17: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/17.jpg)
PrefaceThe base structure I'm using was adopted from BackboneRails
![Page 18: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/18.jpg)
App skeleton& boot
![Page 19: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/19.jpg)
<html> <head> <title>JSDay2014 - Marionette</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script src="libs/jquery.js"></script> <script src="libs/underscore.js"></script> <script src="libs/backbone.js"></script> <script src="libs/backbone.marionette.js"></script> <script src="boot.js"></script> </head> <body>
<div id="header-region"></div> <div id="main-region"></div> <div id="footer-region"></div>
<script> App.start({ environment: 'staging', foo: 'bar' }); </script> ! </body> </html>
index.html
![Page 20: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/20.jpg)
App = new Backbone.Marionette.Application(); !App.on("initialize:before", function (options) { // do something. come on! }); !App.on("initialize:after", function (options) { if (Backbone.history){ Backbone.history.start(); } });
javascript / boot.js
— that’s it!
![Page 21: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/21.jpg)
Regions
![Page 22: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/22.jpg)
App.addRegions({ headerRegion: "#header-region", mainRegion: "#main-region" footerRegion: "#footer-region" });
MyCustomHeaderRegion = Marionette.Region.extend({ el: "#header-region" }); !MyApp.addRegions({ headerRegion: MyCustomHeaderRegion });
You can also define custom classes for your regions:
“Regions provide consistent methods to manage, show and close views in your applications and layouts”
![Page 23: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/23.jpg)
header-region
main-region
footer-region
![Page 24: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/24.jpg)
Showing a view in a region
var myView = new MyView(); !// renders and displays the view App.mainRegion.show(myView); !// closes the current view App.mainRegion.close();
— simple as that.
![Page 25: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/25.jpg)
header-regionmain-region
footer-region
MyView
App.mainRegion.currentView
![Page 26: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/26.jpg)
If you replace the current view with a new view by calling show, it will automatically close the previous view
// Show the first view. var myView = new MyView(); MyApp.mainRegion.show(myView);
no more zombies!
// Replace the view with another. The // `close` method is called for you var anotherView = new AnotherView(); MyApp.mainRegion.show(anotherView);
![Page 27: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/27.jpg)
Marionette Modules
![Page 28: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/28.jpg)
AMD/Require vs Marionette Modules
Take advantage of Marionette's built in module-loader
App.module("MyModule", function (MyModule, App, Backbone, Marionette, $, _) { ! // do stuff here ... ! var myData = "this is private data"; ! MyModule.someData = "public data"; !}); !var theSameModule = MyApp.module("MyModule");
![Page 29: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/29.jpg)
Split your sections/features into modules
![Page 30: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/30.jpg)
Always keep your app organised —
while it grows
![Page 31: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/31.jpg)
Organise each module
App.BlogApp (Marionette Module)BlogApp.Router (Marionette.AppRouter)BlogApp.Posts (Submodule)
Posts.ControllerPosts.View
![Page 32: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/32.jpg)
What about Backbone models/collections?
App.Entities (Marionette module)Entities.Article (Backbone.Model)Entities.Articles (Backbone.Collection)
![Page 33: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/33.jpg)
yeah, about those models...
![Page 34: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/34.jpg)
The magic of Backbone models
![Page 35: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/35.jpg)
App.module("Entities", function (Entities, App, Backbone, Marionette, $, _) { ! Entities.Post = Backbone.Model.extend(); ! Entities.Posts = Backbone.Collection.extend({ model: Entities.Post, url: “path/to/posts.json“ }); !});
entities / posts.js
![Page 36: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/36.jpg)
App.module("BlogApp", function (BlogApp, App, Bk, Mr, $, _) { ! BlogApp.Router = Backbone.Marionette.AppRouter.extend({ appRoutes: { "posts" : "showArticles", "posts/:id" : "showArticle" } }); ! var API = { showArticles: function () { BlogApp.Posts.Controller.Show(); }, showArticle: function (id) { BlogApp.Posts.Controller.Show(id); } }; ! App.addInitializer(function () { new BlogApp.Router({ controller: API }); }); !});
apps / blog / app.js
![Page 37: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/37.jpg)
App.module("BlogApp.Posts", function (Posts, App, Bk, Mr, $, _) { ! Posts.Controller = { Show: function () { ! var layout = new Posts.View({ collection: new App.Entities.Posts }); ! App.mainRegion.show(layout); } }; !});
apps / blog / posts / controller.js
![Page 38: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/38.jpg)
App.module("BlogApp.Posts", function (Posts, App, Backbone, M, $, _) { ! Posts.View = Backbone.Marionette.View.extend({ tagName: "section", className: "posts" }); !});
apps / blog / posts / view.js
![Page 39: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/39.jpg)
Here comes the magic!
Let’s have a look at Marionette Views
![Page 40: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/40.jpg)
Marionette.ItemViewRenders a single item
(Backbone.Model)
Backbone.Model
ItemView
![Page 41: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/41.jpg)
Marionette.CollectionViewRenders the items of a Backbone.Collection
Doesn’t need a template
CollectionView
ItemView Backbone.Model
Backbone.Collection
ItemView Backbone.Model
![Page 42: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/42.jpg)
Marionette.CompositeView
Renders the items of a Backbone.Collection within a wrapper
Extends from Marionette.CollectionView !
Also: Represents both a branch and a tree structure
Therefore: can also render a model if needed
![Page 43: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/43.jpg)
CollectionView
ItemViewBackbone.Model
Backbone.Collection
ItemViewBackbone.Model
ItemViewBackbone.Model
CompositeViewTemplate
+ Backbone.Collection + optional Backbone.Model
Backbone.Model
ItemView
.some-selector
Backbone.Model
ItemView
![Page 44: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/44.jpg)
Before going further, choose your template engine
![Page 45: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/45.jpg)
Underscore templates works out of the box
<script type="template" id="post-template"> <h2> <%- title %> </h2> </script>
![Page 46: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/46.jpg)
you can also override Marionette Renderer:
Backbone.Marionette.Renderer.render = function (template, data) { ! tpl = _.template($( "script.wtf-is-this-" + template ).html()); if (!tpl) throw("Template " + template + " not found!"); ! return tpl(data); !};
<script type="text/template" class="wtf-is-this-post-template"> <h2> <%- title %> </h2> </script>
config/marionette/renderer.js
![Page 47: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/47.jpg)
Using Rails? Go with Jade + JST
gem 'tilt-jade'
Compiles jade templates into js functions for use as clientside templates
![Page 48: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/48.jpg)
Jade is just amazing
.post-content header(class='ng-wtf') h1= title span by #{author} ! if youAreUsingJade p You are amazing ! .body= description
![Page 49: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/49.jpg)
Backbone.Marionette.Renderer.render = (tpl, data) -> path = JST["apps/" + tpl] throw "Template #{tpl} not found!" unless path path data
CoffeeScript...
![Page 50: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/50.jpg)
back to our applet's implement these views
![Page 51: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/51.jpg)
App.module("BlogApp.Posts", function (Posts, App, Bk, Mr, $, _) { ! Posts.PostView = Backbone.Marionette.ItemView.extend({ tagName: "article", className: "post", template: “#post-template" }); ! Posts.View = Backbone.Marionette.CollectionView.extend({ tagName: "section", className: "posts", itemView: Posts.PostView, ! initialize: function (options) { options.collection.fetch(); } }); !});
apps / blog / posts/ view.js
![Page 52: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/52.jpg)
![Page 53: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/53.jpg)
![Page 54: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/54.jpg)
let’s make it better
<script type="text/template" id="post-template"> <a href="#"><%- title %></a> </script> !!<script type="text/template" id="posts-template"> <h1>My nice blog</h1> <ul></ul> </script>
![Page 55: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/55.jpg)
Posts.View = Backbone.Marionette.CompositeView.extend({ tagName: "section", className: "posts", template: “#posts-template", itemView: Posts.PostView, itemViewContainer: "ul", ! initialize: function (options) { options.collection.fetch(); } });
just a few changes to the CollectionView
![Page 56: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/56.jpg)
Posts.PostView = Backbone.Marionette.ItemView.extend({ tagName: "li", className: "post", template: “#post-template", events: { "click a" : "showSinglePost" }, showSinglePost: function (event) { event.preventDefault(); Backbone.history.navigate("posts/" + this.model.get('id')); } });
and some more to the ItemView
![Page 57: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/57.jpg)
![Page 58: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/58.jpg)
Serializing the data
Marionette calls model.toJSON() by default
Posts.PostView = Backbone.Marionette.ItemView.extend({ ... ! // overrides the default behaviour serializeData: function () { return _.extend(this.model.toJSON(), { "foo" : "bar" }); } });
can be overridden by defining serializeData()
![Page 59: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/59.jpg)
Template helpers
<script id="my-template" type="template"> I think that <%= showMessage() %> </script>
Posts.PostView = Backbone.Marionette.ItemView.extend({ ... ! templateHelpers: { showMessage: function () { return this.title + " rocks!"; } }, ! ... });
![Page 60: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/60.jpg)
Modal/Collection events
Backbone.Marionette.CompositeView.extend({ ! modelEvents: { // eq to view.listenTo(view.model, "change:name", view.nameChanged, view) "change:name": "nameChanged" }, ! collectionEvents: { // eq to view.listenTo(view.collection, "add", view.itemAdded, view) "add": "itemAdded" }, ! // ... event handler methods nameChanged: function () { /* ... */ }, itemAdded: function () { /* ... */ } !});
![Page 61: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/61.jpg)
App global requests
// define your request App.reqres.setHandler("show:post", function (id) { Backbone.history.navigate("posts/" + id, true); });
AKA let your modules talk with each other
// use it App.request("show:post", 3);
![Page 62: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/62.jpg)
Marionette in the real world
— 5 minutes of Marionette applied to Cronycle —
![Page 63: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/63.jpg)
header-region with ItemView (User, Backbone.Model)
main-region with CollectionView (Backbone.Collection)
CompositeView (Model + Collection)
ItemView (Model)
ItemView (Model)
![Page 64: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/64.jpg)
left-sidebar-region with CompositeView
![Page 65: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/65.jpg)
Modal windows, just an overlay region
![Page 66: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/66.jpg)
Modal region
App.module("Modals", function (Modals, App, Backbone, Marionette, $, _) { ! Modals.Region = Marionette.Region["extends"]({ el: "#modal-region", open: function(view) { $.magnificPopup.open(view); }, close: function() { $.magnificPopup.instance.close(); } }); !!!!!!!!!!!!!!!!});
Modals.start = function () { App.addRegions({modalRegion: Modals.Region}); };
App.reqres.setHandler("alert", function (title) { view = new MyModalWindow({ title: title }); return App.modalRegion.show(view); });
// This is how you use it App.request("alert", "Roflcopter!");
![Page 67: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/67.jpg)
Fetching for new articles
![Page 68: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/68.jpg)
1. define a comparator on your collection
Fetching for new articles
var Entities.Posts = Backbone.Collection.extends({ model: Entities.Post, url: "/posts", ! comparator: function (model) { return -parseInt(model.get('published_at'), 10); } });
![Page 69: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/69.jpg)
2. define a custom fetch method
Fetching for new articles
var Entities.Posts = Backbone.Collection.extends({ ! fetchNewPosts: function (callback) { this.fetch({ url: "posts/?min_ts=#{@first().get('published_at')}", update: true, add: true, remove: false } !});
![Page 70: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/70.jpg)
Fetching for new articles
3. override the appendHtml method on your CompositeView
var YourItemView = Backbone.Marionette.CompositeView.extends({ ! ui: { linksContainer: ".posts-container" }, ! appendHtml: function (collectionView, itemView, index) { if (index == 0){ this.ui.linksContainer.prepend(itemView.$el); } else { childAtIndex = this.ui.linksContainer.find("> article:eq(" + index + ")"); ! if (childAtIndex.length) { childAtIndex.before(itemView.$el); } else { this.ui.linksContainer.append(itemView.$el); } } } !});
![Page 71: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/71.jpg)
put a test on it
https://github.com/bradphelan/jasminerice
+ jasmine-rice for Rails users
If you like your goat...
![Page 72: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/72.jpg)
describe("Navigating to the posts route", function () { ! it("should display some articles", function () { ! Backbone.history.navigate("/posts", true); ! expect(App.mainRegion.$el.find('article.post').length).toBeGreaterThan(0); ! expect(App.mainRegion.currentView.collection.at(0).get('title')).toBe('foo'); ! }); });
![Page 73: Make your Backbone Application dance](https://reader033.vdocuments.mx/reader033/viewer/2022052617/53f8ee7d8d7f7253318b4980/html5/thumbnails/73.jpg)
github.com/squallstar/jsday2014-marionettejs
The project we just created:
(the dummy blog, not cronycle!)
Nicholas Valbusa@squallstar - squallstar.it
THANKS! Q/A?
https://joind.in/11286