backbone.jsのCollectionのフィルタリング
backbone.jsに慣れようと思って、ちょこちょこサンプルを書いているわけですが、
今日はインクリメンタルサーチっぽいUIを書いて見ました。
サンプルはこちら
http://dl.dropbox.com/u/494487/backbone-sample/filtering/index.html
データは静的にもってるだけで、サーバーからfetchとかはしてません。
ModelとCollection
// Model var Track = Backbone.Model.extend({}); // Collection var TrackList = Backbone.Collection.extend({ model: Track, search : function(query){ if(query == "") return this; var pattern = new RegExp(query, "gi"); return _(this.filter(function(data) { return pattern.test(data.get("title")); })); } });
Collectionに絞込み用のsearch関数を持たせてます。
戻り値を_()で囲むことによって、絞り込み結果に対して、view側でunderscore.jsのメソッドが使えます
View
// main view var AppView = Backbone.View.extend({ events: { "keyup #new-input": "search" }, initialize: function() { this.template = _.template($("#list-container").html()); this.collection.bind("all", this.render, this); this.collection.bind("reset", this.addAll, this); // this.collection.fetch() }, render: function(data) { $(this.el).html(this.template); return this; }, renderList: function(entires){ $("#trackList").html(""); entires.each(this.addOne); return this; }, search: function(){ var query = $('#new-input').val(); this.renderList(this.collection.search(query)); }, addOne: function(track){ var view = new TrackView({model: track}); $("#trackList").append(view.render().el); }, addAll: function(){ this.collection.each(this.addOne); } });
eventsに{"keyup #new-input": "search"}を設定して、入力があった場合にviewのsearch関数が呼ばれるようになります。
viewのsearch関数は保持しているcollectionのsearchメソッドを呼び、絞り込んだ結果をrenderList関数に渡します。
全体では以下のような感じです。
$(function(){ // Model var Track = Backbone.Model.extend({}); library = [new Track({title: "I Saw Her Standing There"}), new Track({title: "Misery"}), new Track({title: "Anna (Go To Him)"}), new Track({title: "Chains"}), new Track({title: "Boys"}), new Track({title: "Ask Me Why"}), new Track({title: "Please Please Me"}), new Track({title: "Love Me Do"}), new Track({title: "P.S. I Love You"}), new Track({title: "Baby It's You"}), new Track({title: "Do You Want To Know A Secret"}), new Track({title: "A Taste Of Honey"}), new Track({title: "There's A Place"}), new Track({title: "Twist And Shout"})]; // Collection var TrackList = Backbone.Collection.extend({ model: Track, search : function(query){ if(query == "") return this; var pattern = new RegExp(query, "gi"); return _(this.filter(function(data) { return pattern.test(data.get("title")); })); } }); // Collection instance var tracks = new TrackList(library); // each track view var TrackView = Backbone.View.extend({ initialize : function(){ this.template = _.template($("#track-template").html()); }, render: function(data) { $(this.el).html(this.template(this.model.toJSON())); return this; } }); // main view var AppView = Backbone.View.extend({ events: { "keyup #new-input": "search" }, initialize: function() { this.template = _.template($("#list-container").html()); this.collection.bind("all", this.render, this); this.collection.bind("reset", this.addAll, this); // this.collection.fetch() }, render: function(data) { $(this.el).html(this.template); return this; }, renderList: function(entires){ $("#trackList").html(""); entires.each(this.addOne); return this; }, search: function(){ var query = $('#new-input').val(); this.renderList(this.collection.search(query)); }, addOne: function(track){ var view = new TrackView({model: track}); $("#trackList").append(view.render().el); }, addAll: function(){ this.collection.each(this.addOne); } }); window.App = new AppView({collection: tracks}); $("#content-container").append(window.App.render().el); window.App.addAll(); });
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <title>backbone sample - filter</title> </head> <body> <h1>BackBone Filter Sample</h1> <div id="content-container"> </div> <script id="list-container" type="text/template"> <div> <div> <input type="text" id="new-input" placeholder="Type something"> <div class="block"> <ul id="trackList" class="list"> </ul> </div> </div> </div> </script> <script id="track-template" type="text/template"> <li> <h4><%= title %></h4> </li> </script> <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7/jquery.min.js" type="text/javascript" charset="utf-8"></script> <script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.2.2/underscore-min.js" type="text/javascript" charset="utf-8"></script> <script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.5.3/backbone-min.js" type="text/javascript" charset="utf-8"></script> <script src="app.js" type="text/javascript"></script> </body> </html>