こんにちは。きんくまです。
BackboneのCollectionで条件が2つ以上あるようなソートをしたいときのはなしです。
例)
従業員のプロパティが
・名前
・部署
・年齢
だったときに、Collectionのソート順を
1. 部署ごと
2. 同じ部署だったら年齢の高い順
にしようとしました。
とりあえずModelまで定義しちゃうとこんな感じになりました。
部署は名前じゃなくて、部署コードみたいな感じでenumで定義しときました。
module ex{ export enum Division{ Sales = 0 ,ResearchAndDev ,Personnel } export class DivisionUtil{ static names:string[] = [ "営業部" ,"研究開発部" ,"人事部" ]; static getNameByNumber(num:Division):string{ return DivisionUtil.names[num]; } } export class Employee extends Backbone.Model{ name:string; age:number; division:Division; constructor(attrs?:any, options?:any){ super(attrs, options); } initialize(){ this.name = this.get('name'); this.age = this.get('age'); this.division = this.get('division'); } toString(){ return this.name + " (" + this.age + ") " + DivisionUtil.getNameByNumber(this.division); } } }
それで、ここからが本題です。
公式のドキュメントによると、Collectionのsortをするときは、comparatorというプロパティが使われるみたいです。
デフォルトではcomparatorは入ってなくて、そのときaddするとソートはしない。
けどcomparatorを設定してあれば、addするときはそいつで自動ソートしてくれるみたい。
addするのに自動ソートなしでしたいってときは、{sort: false}をaddのオプションにいれればOK。
でcomparatorは以下の3種類からいづれかいれることができます。
1. 引数ひとつの関数
2. 引数ふたつの関数
3. 文字列(プロパティ名)
1と3はググるとサンプルでよく書いてあるけど、複雑なソートは2が良いと思います。
で、今回は条件が2つあるので、引数ふたつで書いてみました。
引数2つの関数はJavaScriptのネイティブのArrayのsortの引数と同じ形式で、数値の-1か0か1を返しておけば適当にやってくれます。
(私の場合、降べき昇べき順を頭で考えられないので、やってみて思い通りでなかったら、毎回1と-1のところを入れ替えて、しのいでますw)
module ex{ export class EmployeesCollection extends Backbone.Collection{ constructor(models?:any){ super(models, { model:Employee }); } initialize(){ this.setComparator(); } //ソート順を決める setComparator(){ var emp1:Employee ,emp2:Employee; //年齢順のソート var sortByAge = (anEmp1:Employee, anEmp2:Employee)=>{ if(anEmp1.age < anEmp2.age){ return 1; }else if(anEmp1.age > anEmp1.age){ return -1; } return 0; }; //部署ごとのソート this.comparator = (m1:Backbone.Model, m2:Backbone.Model)=>{ emp1 = <Employee>m1; emp2 = <Employee>m2; if(emp1.division < emp2.division){ return -1; }else if(emp1.division > emp2.division){ return 1; } //同じ部署だったら年齢順で return sortByAge(emp1, emp2); }; } } }
ためしてみます。
$(()=>{ var employees = new ex.EmployeesCollection(); employees.add([ {name:"たなか", age:50, division:1} ,{name:"さとう", age:62, division:0} ,{name:"すずき", age:31, division:2} ,{name:"なかにし", age:23, division:1} ,{name:"ふくやま", age:36, division:1} ,{name:"ひらい", age:47, division:2} ,{name:"かねこ", age:33, division:0} ]); employees.models.forEach((elem)=>{ console.log(elem.toString()); }); });
出力結果はこうなりました。目的のソート順になったので良かったです。
さとう (62) 営業部 かねこ (33) 営業部 たなか (50) 研究開発部 ふくやま (36) 研究開発部 なかにし (23) 研究開発部 ひらい (47) 人事部 すずき (31) 人事部
■ 自作iPhoneアプリ 好評発売中!
・フォルメモ - シンプルなフォルダつきメモ帳
・ジッピー電卓 - 消費税や割引もサクサク計算!
■ LINEスタンプ作りました!
毎日使える。とぼけたウサギ