Sencha Advent Calendar 2015 22日目
http://www.adventar.org/calendars/1041
ツリーリストを触ってみる
こんにちは。xenophyの菅井です。
お久しぶりです。今回のアドベントカレンダーも終盤に差し掛かってきました。
自分の番が終わればあと2回です。
アドベントカレンダーが終わったら、もう今年も終わりますねー。なんだか早かった。
さて今日から明日にかけてExt JS 6から追加されたコンポーネントで最近個人的に使った
ツリーリスト(Ext.list.Tree
)をコード触りつつ簡単に使い方を紹介していこうと思います。
ツリーリストについて
ExtJSのツリーといえば元々ツリーパネルがありました。
あちらはグリッドパネルみたいにツリーの横にカラムを追加できたり
リーフにチェックボックスを付けたりツリー表示に色々拡張ができました。
今回紹介するツリーリストはほんとにツリー状のリストというだけで
すごくシンプルな作りなのでナビゲーションの機能を実装するのに向いていると考えています。
さらにツリーリストにはツリーパネルにはない機能があって
「micro」モードと呼ばれているものがあります。
この「micro」モードになるとツリーリストはアイコンのみのリスト表示になって
その分リストの幅を狭く表示できるのでナビゲーションの縮小機能を
とても簡単に実装することができます。
というわけで今日はこのツリーリストを使ってナビゲーションのベースを作成していきます。
今日の目標はツリーパネルの表示と「micro」モード切り替え部分の実装です。
まずは
Ext JS 6のアプリケーションを新規で作成します。
%
sencha -sdk
~/Library/Sencha/ext-6.0.1/generate app
ExtJs6TreeList extjs-6-treelist
- Sencha CmdやSDKの詳細についてはここでは説明していません。別の日の記事が参考になると思います!
Sencha Cmdでローカルのサーバーを起動
%
sencha web start
ExtJS6の新規アプリケーションの画面が表示されるのを確認します。
間仕切り
はじめに新規で作成したアプリケーションの画面にヘッダー、サイドバー、スクリーンの枠組みを
それぞれ作っていきます。
- 今回ナビゲーションを表示するのはサイドバーの部分です。
作成されたディレクトリをたどると~/extjs-6-treelist/classic/src/view/main/Main.js
というファイルがあるので
これをベースに改造していきます。
- 今回modernは省きます。ツリーリスト自体はmodernも対応しています。
このMain
クラスですがExt.tab.Panel
を継承しているので普通のパネルにします。
さらにそれぞれのレイアウトはボーダーで切っていきます。
さらにさらに色々いらないconfig等を外して下記のようになりました。
ソース
Ext.define('ExtJs6TreeList.view.main.Main', {
extend: 'Ext.panel.Panel',
xtype: 'app-main',
requires: [
'Ext.plugin.Viewport',
'Ext.window.MessageBox',
'ExtJs6TreeList.view.main.MainController',
'ExtJs6TreeList.view.main.MainModel'
],
controller: 'main',
viewModel: 'main',
// ボーダーレイアウト
layout: 'border',
// パネル全体に枠線を出す
defaults: {
frame: true
},
items: [{
// ヘッダー部分のパネル
xtype : 'panel',
region : 'north',
height : 50,
name : 'header',
html : 'ヘッダー'
}, {
// サイドバー部分のパネル
xtype : 'panel',
region : 'west',
width : 300,
name : 'sidebar',
html : 'サイドバー'
}, {
// スクリーン部分のパネル
xtype : 'panel',
region : 'center',
name : 'screen',
html : 'スクリーン'
}]
});
画面
ツリーリストを表示
やっと主役の登場です。
今作成したサイドバーパネルにツリーリストを表示するため
ツリーリストを継承したViewを作成します。
ツリーストアの作成
まずツリーに表示させるデータを持ったツリーストアを下記のように作成します。
階層のデータになっているのはなんとなく解ると思います。
iconCls : 'x-fa fa-dashboard'
でリストの横に表示するアイコンを指定しています。
- この指定はツリーパネルも同様です。
ファイル名:~/extjs-6-treelist/app/store/Navigation.js
ソース:
Ext.define('ExtJs6TreeList.store.Navigation', {
extend: 'Ext.data.TreeStore',
alias: 'store.navigation',
root: {
expanded : true,
children : [{
text : 'ダッシュボード',
iconCls : 'x-fa fa-dashboard',
leaf : true
}, {
text : '日報',
iconCls : 'x-fa fa-edit',
leaf : true
}, {
text : '管理',
iconCls : 'x-fa fa-gears',
expanded : true,
children : [{
text : 'アカウント',
iconCls : 'x-fa fa-users',
leaf : true
}, {
text : 'プロフィール',
iconCls : 'x-fa fa-user',
leaf : true
}, {
text : '権限',
iconCls : 'x-fa fa-bolt',
leaf : true
}]
}]
}
});
ツリーリストの作成
ツリーリストはMVVMの構成で作ってみます。
中身はすごい簡単で、単純にExt.list.Tree
を継承して
データソースに上記のストアを指定しているだけです。
xtype
は「navigation」とします。
View
ファイル名:~/extjs-6-treelist/classic/src/view/navigation/Main.js
ソース:
Ext.define('ExtJs6TreeList.view.navigation.Main', {
extend: 'Ext.list.Tree',
xtype: 'navigation',
requires: [
'ExtJs6TreeList.view.navigation.MainController',
'ExtJs6TreeList.view.navigation.MainModel',
'ExtJs6TreeList.store.Navigation'
],
store: {
type: 'navigation'
}
});
ViewModel
ファイル名:~/extjs-6-treelist/app/view/navigation/MainModel.js
ソース:
Ext.define('ExtJs6TreeList.view.navigation.MainModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.navigation'
});
ViewController
ファイル名:~/extjs-6-treelist/app/view/navigation/MainController.js
ソース:
Ext.define('ExtJs6TreeList.view.navigation.MainController', {
extend: 'Ext.app.ViewController',
alias: 'controller.navigation'
});
Mainの修正
~/extjs-6-treelist/classic/src/view/main/Main.js
のファイルを修正します。
まずrequires
の配列の中に作成したツリーリストのクラスExtJs6TreeList.view.navigation.Main
を追加します。
次にサイドバーのitems
の中にツリーリストのxtype
を指定します。そのときhtml:'サイドバー'
は削除します。
{
// サイドバー部分のパネル
xtype : 'panel',
region : 'west',
width : 300,
name : 'sidebar',
items : [{
xtype: 'navigation'
}]
}
リフレッシュ
Mainにツリーリストのクラスを追加したのでsencha app refresh
でクラスの紐付けを更新します。
%
sencha app refresh
画面
上記の修正後画面を表示するとツリーリストが表示されています。
ツリーリストの「micro」モード
ここまでできれば今回の目標は達成です。あともう少し。
「micro」モード用のチェックボックスを配置
ツリーリストを「micro」モードにフォームチェンジするためのチェックボックスを配置します。
ヘッダーに置くのでMainのヘッダーパネルを下記のように修正します。
{
// ヘッダー部分のパネル
xtype : 'panel',
region : 'north',
height : 50,
name : 'header',
items : [{
// 「micro」モードにフォームチェンジするためのチェックボックス
xtype : 'checkboxfield',
boxLabel : 'change micro mode',
name : 'changeMicroMode',
handler : 'onChangeMicroMode'
}]
}
次にチェックボックスをチェックしたときに「micro」モードにしたいのでMainのViewControllerの中で
下記のイベントハンドラーを実装します。
メソッドの名前はViewのhandler
に指定してあるonChangeMicroMode
です。
このメソッドの中でツリーリストのViewを取得してsetMicro
のメソッドを利用し
「micro」モードと通常モードの切り替えを行っています。
その際モード毎にサイドバーパネルの幅を切り替えています。
Ext.define('ExtJs6TreeList.view.main.MainController', {
extend: 'Ext.app.ViewController',
alias: 'controller.main',
onChangeMicroMode: function(cb, checked) {
var me = this,
view = me.getView(),
navigation = view.down('treelist[xtype=navigation]'),
sidebar = view.down('panel[name=sidebar]');
// 「micro」モード切り替え
navigation.setMicro(checked);
// サイドバーパネルの幅切り替え
sidebar.setWidth(checked ? 36 : 300);
}
});
ここまできたら最後にsencha app build
をして画面を表示したいのですが
今のままだとビルドエラーになってしまいます。
- そしておそらくビルドしないとチェックボックスのスタイルが当たらない
ビルドエラーになる理由は元々タブパネルだったMainのViewを普通のパネルに変えているので
元々新規作成のときにつくられたタブパネル向けのsassの記述が残ったままになっているためです。
なので~/extjs-6-treelist/classic/sass/src/view/main/Main.scss
の中身を削除してビルドします。
%
sencha app build
表示確認
最後に画面表示して「micro」モードにしてみる。
「micro」モード表示できました!サイドバーパネルも「micro」モードに合わせて狭くなっています。
次回予告
目標のツリーリストの表示と「micro」モードの切り替えまでできました。
ただ今のままだと階層に関係なくフラットに表示されていたり
通常モードと「micro」モードのアイコンの位置が違うので
切り替えていると動きが不自然に見えたります。
明日はsassメインでこの辺の見た目のカスタマイズをしてみます。