HOME > 開発者向けBLOG > Ext JS >  Ext JS4 MVCアプリケーション開発 第二回

Technology Note 開発者向けBLOG

Ext JS

Ext JS4 MVCアプリケーション開発 第二回

こんにちは、ゼノフィ齋藤です。

はじめに

前回のエントリにてコントローラ・ビューを作成しViewportが表示されました。
今回はそのViewportにBorderレイアウトを指定し、下記の流れにてコントローラーにイベントハンドラを設定していきましょう。
  • 各ビューの設置
  • Viewportへ各ビューを定義
  • 各コントローラーを設置
  • コントローラーの使用宣言

各ビューの設置

ExtJS4 MVCにおけるビューは、ExtJS3におけるコンポーネント定義に近いです。
それではExt.application.appFolderで指定したディレクトリ配下に、Panelを継承した下記3つのビューを設置しましょう。
・src/app/view/Header.js
1
2
3
4
5
Ext.define('Xenophy.view.Header', {
    alias: 'widget.xenophy-header',
    extend: 'Ext.panel.Panel',
    title: 'Header'
});
・src/app/view/Navi.js
1
2
3
4
5
Ext.define('Xenophy.view.Navi', {
    alias: 'widget.xenophy-navi',
    extend: 'Ext.panel.Panel',
    title: 'Navi'
});
・src/app/view/Center.js
1
2
3
4
5
Ext.define('Xenophy.view.Center', {
    alias: 'widget.xenophy-center',
    extend: 'Ext.panel.Panel',
    title: 'Center'
});
Header/Navi/Center各パネルには、クラスエイリアス(alias)を指定します。クラスエイリアスとはExtJS4から実装された機構で、コンポーネントだけではなくクラスもクラスマネージャーにより管理され、xtypeの代わりにクラスエイリアスを利用してインスタンス化出来るようになりました。
ここではalias/xtypeに関しての詳細な説明は割愛しますが、非常に重要な部分なので別途学習することをお勧めします。

Viewportへ各ビューを定義

これで各ビューが用意出来ましたが、このままでは当然画面には表示されません。
Viewportクラスに作成した各ビューを定義する必要があります。
・src/app/view/Viewport.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Ext.define('Xenophy.view.Viewport', {
    uses: [
        'Xenophy.view.Header',
        'Xenophy.view.Navi',
        'Xenophy.view.Center'
    ],
    layout: {
        type: 'border',
        padding: 5
    },
    extend: 'Ext.container.Viewport',
    items: [{
        xtype: 'xenophy-header',
        height: 80,
        padding: '0 0 5 0',
        region: 'north'
    }, {
        xtype: 'xenophy-navi',
        region: 'west',
        split: true,
        width: 240
    }, {
        xtype: 'xenophy-center',
        region: 'center'
    }]
});
ViewportクラスにはそれぞれのパネルをExt.Loaderで読み込ませるため、usesに各ビューを配列で指定します。これによりViewportクラスが生成される前に、各パネルの読み込みが完了します。

各コントローラーの設置

それでは続いて作成したビューに対応するコントローラーを作成していきましょう。
ここではHeaderにボタンを設置しクリック制御を行います。
またアイコンを表示しますので、こちらよりcss・画像をダウンロードし、resourcesディレクトリをドキュメントルート直下に配置してください。
それではボタン制御を行うHeaderコントローラーを作成していきましょう。
・src/app/controller/Header.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Ext.define('Xenophy.controller.Header', {
    extend: 'Ext.app.Controller',
    init: function() {
        var me = this;
        me.control({
            'xenophy-header button[action=button1]': {
                click: function() {
                    Ext.Msg.alert('ボタン1', 'クリックされました。');
                }
            },
            'xenophy-header button[action=button2]': {
                click: function() {
                    Ext.Msg.alert('ボタン2', 'クリックされました。');
                }
            },
            'xenophy-header button[action=button3]': {
                click: function() {
                    Ext.Msg.alert('ボタン3', 'クリックされました。');
                }
            }
        });
    }
});
initで初期化が行われるタイミングで、controlメソッドを利用してイベントハンドラを設定していきます。この時、どのコンポーネントに対してのイベントハンドラを定義するかは、コンポーネントクエリーを利用します。コンポーネントクエリーもExtJS4から実装された機能で、CSSセレクタと似たような機能で、複雑にネストするアプリケーション内のコンポーネントをセレクタを利用して取得する機能です。
ここでは 「xenophy-header(xtype名)の中にある、button(xtype名)のaction属性が=以降の物」を取得しています。
それではコントローラーに合わせて、上記で作成したHeaderのビューを修正していきましょう。
・src/app/view/Header.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Ext.define('Xenophy.view.Header', {
    alias: 'widget.xenophy-header',
    extend: 'Ext.container.Container',
    defaults: {
        xtype: 'container'
    },
    layout: 'hbox',
    items: [{
        html: {
            tag: 'h1',
            html: 'Code.6 - Xenophy Application'
        },
        flex: 1
    }, {
        xtype: 'toolbar',
        width: 217,
        items: [{
            text: 'ボタン1',
            iconCls: 'x-icon-1',
            action: 'button1'
        }, {
            text: 'ボタン2',
            iconCls: 'x-icon-2',
            action: 'button2'
        }, {
            text: 'ボタン3',
            iconCls: 'x-icon-3',
            action: 'button3'
        }]
    }]
});
ツールバー内に3つのボタンを配置し、それぞれaction属性を指定していますが、これによりコントローラで指定したコンポーネントクエリーで、コンポーネントオブジェクトが取得できるようになります。
またここでHeaderの親クラスをPanelからContainerへ変更していますが、Containerの方が親クラスにあたりPanelに比べて機能が少ない分高速に動作するためです。Panel独自の機能を使用する必要が無いときは、なるべくContainerを使用すると良いでしょう。
同様に、Navi/Centerのコントローラーも用意しましょう。
ここでは、特に処理が無いので、initが空のクラスになります。
・src/app/controller/Navi.js
1
2
3
4
5
Ext.define('Xenophy.controller.Navi', {
    extend: 'Ext.app.Controller',
    init: function() {
    }
});
・src/app/controller/Center.js
1
2
3
4
5
Ext.define('Xenophy.controller.Center', {
    extend: 'Ext.app.Controller',
    init: function() {
    }
});

コントローラー使用宣言

これでコントローラーの作成は終わりましたが、このままではまだ動作しません。app.jsにてMainコントローラー同様、利用することを宣言する必要があります。
・src/app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Ext.Loader有効化
Ext.Loader.setConfig({
    enabled: true
});
// アプリケーション設定
Ext.application({
    // Viewport自動生成
    autoCreateViewport: true,
    // アプリケーション名
    name: 'Xenophy',
    // アプリケーションフォルダパス
    appFolder: 'src/app',
    // 使用コントローラー定義
    controllers: ['Main', 'Header', 'Navi', 'Center'],
    // アプリケーション起動時イベントハンドラ
    launch: function() {
    }
});
controllersの配列に作成したコントローラーを追加しました。これにより初めてコントローラーとして動作する事になります。またコントローラーが複数ある時には、配列に定義した順にinitがコールされる事も、併せて押さえておきましょう。
それでは実際に画面で確認してみましょう。

イベントハンドラ内のthis

補足ですが、先程コントローラー内で定義したclickイベントハンドラ内のthisは何になるでしょうか?
答えは、「定義されているコントローラークラスオブジェクト」になります。
コントローラーはここまで説明した以外にも大変便利な機能が存在しますが、thisで簡単にアクセスすることができます。

今回のソース

今回までのソースサンプルはこちらです。

おわりに

第二回ではMVCアプリケーションのVC部分が作成でき、ビューからビジネスロジックが切り離されました。
今回は各ビュー全てにコントローラーを設置しましたが、全てのcontrolメソッドを、Mainコントローラーに定義しても動きますが、それではソースコードが煩雑になりますしチーム開発の際に混乱を来すでしょう。
そのため場合によってはN個のviewに対して、1controllerになる事もあるでしょうが、基本は1viewに対して、1controllerを作成するのが望ましいでしょう。
ただ1対1の関係でも、あるコントローラが別のビューをハンドリングする機会も当然出てくると思います。
次回はコントローラーからビューへのアクセス方法に関して、さらに説明していきたいと思います。

PAGETOP