ExtJS入門22 グリッドのイベント処理(ダブルクリック、右クリック)
前回はツールバーでグリッドの情報を取得し、ポップアップで表示しました。今回はグリッドのダブルクリックと右クリックのイベントで詳細を表示する処理を実行します。
グリッドのダブルクリックと右クリック(コンテクストメニュー)で処理を実装することで、より直感的なグリッドの操作が可能になります。
サンプルは前回のExJS入門21 グリッド・セレクション・モデルをベースにイベントの処理を追加しています。
グリッドパネル関連の過去の記事はこちらからです。
- ExtJSで楽しくRIA業務アプリ開発 ExJS入門17 グリッド・パネル 基本編
- ExtJSで楽しくRIA業務アプリ開発 ExtJS入門18 グリッド レンダラーを使ってデザインを変える
- ExtJS入門19 グリッドにページング機能を追加する
- ExtJS入門20 グリッドにフィルタリング機能を追加する
- ExtJS入門21 グリッド・セレクション・モデル
リファレンスはこちらから
今回はExt.menu.Menuクラスを右クリックに仕込んでいます。
ExtJS -3.0 日本語APIドキュメント – Ext.grid.GridPanelクラス
http://extdocs.xenophy.com/?class=Ext.grid.GridPanel
ExtJS -3.0 日本語APIドキュメント – Ext.menu.Menuクラス
http://extdocs.xenophy.com/?class=Ext.menu.Menu
PHP:
<?php
$limit = $_POST['limit'];
$start = $_POST['start'];
$name = $_POST['name'];
//全データ
$data = array(
array(
'id'=>1,
'rank'=>1,
'name'=>'IE',
'percentage'=>62.69,
'url' => 'http://www.microsoft.com/japan/windows/products/winfamily/ie/default.mspx',
'img' => '../img/ie64.png'
),
array(
'id'=>2,
'rank'=>2,
'name'=>'Firefox',
'percentage'=>24.61,
'url' =>'http://mozilla.jp/firefox/',
'img' => '../img/firefox64.png'
),
array(
'id'=>3,
'rank'=>3,
'name'=>'Chrome',
'percentage'=>4.63,
'url' => 'http://www.google.com/chrome/',
'img' => '../img/chrome64.png'
),
array(
'id'=>4,
'rank'=>4,
'name'=>'Safari',
'percentage'=>4.46,
'url'=> 'http://www.apple.com/jp/safari/',
'img' => '../img/safari64.png'
),
array(
'id'=>5,
'rank'=>5,
'name'=>'Opera',
'percentage'=>2.40,
'url' => 'http://jp.opera.com/',
'img' => '../img/opera64.png'
),
array(
'id'=>6,
'rank'=>6,
'name'=>'Opera Mini',
'percentage'=>0.53,
'url' => 'http://jp.opera.com/',
'img' => '../img/opera64.png'
)
);
if ($name) {
$newData = array();
foreach($data as $val){
if(stristr($val['name'],$name)) {
$newData[] = $val;
}
}
$data = $newData;
}
if ($limit && $start + $limit <= count($data)) {
//ページング用
$rows = array_slice($data,$start,$limit);
}else {
//ページングしない
$rows = $data;
}
$res = array(
'success' => true,
'total' => 6,
'rows' => $rows
);
header("Content-Type: text/javascript; charset=utf-8");
echo json_encode($res);
die();
HTML:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>ExtJS名古屋勉強会 クリックイベント</title>
<!--Ext JS CSS-->
<link rel="stylesheet" href="../js/ext/resources/css/ext-all.css" type="text/css" />
<!--Ext JS-->
<script type="text/javascript" src="../js/ext/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../js/ext/ext-all.js"></script>
<script type="text/javascript" src="grid-click.js"></script>
<style TYPE="text/css">
<!--
.info {background-image: url(../img/icon/information.png) !important;}
.delete {background-image: url(../img/icon/delete.png) !important;}
-->
</style>
</head>
<body>
<div style="width:500px;margin:0 auto;padding:15px;background-color:#D3E1F1;font-size:small;">
<p style="font-weight:bold;padding:3px;margin-bottom:10px;">
クリックイベントの処理を設定します。
</p>
<ul>
<li>rowdblclick:行のダブルクリック</li>
<li>rowcontextmenu:行の右クリック</li>
</ul>
<div id="grid"></div>
<br/>
Java Script:<a href="grid-click.js">grid-click.js</a><br/>
PHP(JSONデータ):<a href="data.php">data.php</a><br />
</div>
</body>
</html>
Java Script:
//グリッドイベント
Ext.onReady(function()
{
//詳細表示処理
//詳細表示イベント実行時にこの関数を呼ぶ。
var showInfo = function(record) {
if(!record) {return;};
//表示するメッセージ
var msg = new Ext.XTemplate(
'<div style="width:200px; text-align:center;">',
'ブラウザ名:{name}<br/>',
'順位:{rank}<br/>',
'シェア:{percentage}%<br />',
'<a href="{url}" target="_blank">DOWNLOAD</a><br/>',
'<img src="{img}" />',
'</div>').apply(record.data);
Ext.Msg.alert('選択中のブラウザ',msg);
};
//1.データを用意
//今回はPHPでdata.phpでJSONを返しています。
//2.データストアを用意
var store = new Ext.data.JsonStore({
url:'data.php',//php等が使えない場合はここをdata:'data.json'としてローカルファイルの取得してもよいです。
root:'rows', //実際のデータ位置(プロパティ名)
totalProperty:'total', //全件数を返すプロパティ名を指定
fields:[
{name:'id'},
{name:'rank'},
{name:'name'},
{name:'percentage',type:'float'},
{name:'url',type:'url'},
{name:'img',type:'url'},
],
autoLoad:true //描写後に自動的に初回のリクエストをかける
});
//3.SelModelの設定
//今回は一度に一つの行しか選択できないようにしている。
var sm = new Ext.grid.RowSelectionModel({
singleSelect:true
});
//4.カラムモデルを用意
var column = new Ext.grid.ColumnModel([
{
id:'rank',
header:'順位',
dataIndex:'rank',
width:50
},
{
id:'name',
header:'ブラウザ名',
dataIndex:'name',
width:100
},
{
id:'percentage',
header:'シェア',
dataIndex:'percentage',
width:80
},
{
id:'id',
header:'ID',
dataIndex:'id',
width:20
}
]);
var contextMenu = new Ext.menu.Menu({
items: [
{
text:'詳細表示',
iconCls:'info',
scope:this,
handler: function(btn){
var record = grid.selModel.getSelected();
showInfo(record);
}
},{
text:'削除',
iconCls:'delete',
scope:this,
handler:function(btn){
var record = grid.selModel.getSelected();
Ext.Msg.alert('選択中のブラウザの削除', '「' + record.get('name') + '」を削除しますか?');
}
}
]
});
//5.グリッドパネルの作成
var grid = new Ext.grid.GridPanel({
renderTo:'grid',
id:'my-grid',
autoExpandColumn:'name',
title:'SingleSelectのグリッドパネル',
height:210,
width:400,
cm:column,
sm:sm,
store:store,
tbar:[
{
text:'詳細情報表示',
iconCls:'info',
handler:function(btn){
var record = grid.selModel.getSelected();
showInfo(record);
}
},
{
text:'削除',
iconCls:'delete',
handler:function(btn){
var record = grid.selModel.getSelected();
Ext.Msg.alert('選択中のブラウザの削除', '「' + record.get('name') + '」を削除しますか?');
}
}
],
//イベントを設定する。
/**
* 今回はどちらのイベントも引数は同じ。
* rowdblclick:ダブルクリックイベント
* rowcontextmenu:ダブルクリックイベント
* grid:グリッド
* row:ダブルクリックした行のインデックス
* e:イベントオブジェクト
*
*/
listeners:{
rowdblclick:function(grid, row, e){
var record = grid.getStore().getAt(row);
showInfo(record);
},
rowcontextmenu:function(grid, row, e){
//右クリックでセレクト処理(セレクトしたものを後で右クリックメニューで取得する)
grid.getSelectionModel().selectRow(row);
//右クリックイベントを止める。ここで止めないとブラウザの右クリックメニューが表示されてしまう。
e.stopEvent();
//コンテクストメニューを表示
contextMenu.showAt(e.getXY());
}
}
});
});
実行結果:

グリッドの部分は基本的に前回のサンプルのままです。
ExtJSのクラスに定義されているイベントを処理するときはコンフィグ・オプションのlistenersにイベントごとの処理を記述していきます。
今回はExt.grid.GridPanelクラスのrowdblclickイベントとrowcontextmenuイベントの処理を書いていきます。listenersコンフィグはオブジェクトで指定します。それぞれのイベントに対応するプロパティ名に処理を定義します。各イベントは違った引数を持ちます。ExtJSの標準クラスのイベントについては各クラスのAPIリファレンスのイベント項目に記載されています。
今回は偶然ですがrowdblclickとrowcontextmenuのイベントは同じ引数を持ちます。
- 第1引数:対象のグリッド・オブジェクト
- 第2引数:クリックした、行のインデックス
- 第3引数:イベントオブジェクト
-
第1引数のグリッドオブジェクトと第2引数のインデックスを使ってクリックした行に対応するストアのレコードを取り出すことができます。具体的には以下のようにstoreのgetAt()メソッドを使って取り出します。グリッドではグリッドのストアからrecordさえ取り出せれば後は自由に処理を実行できます。
では実際にイベント処理を見ていきますrowdblclickは比較的シンプルですが、rowcontextmenuはほんの少しだけ複雑です。まずrowdblclickでイベント処理の感覚をつかむでおくと良いと思います。
・グリッドのダブルクリック (rowdblclickイベント)
listeners:{
rowdblclick:function(grid, row, e){
var record = grid.getStore().getAt(row);
/**
* 上の処理はこう書いても同じです。
* var store = grid.getStore();
* var record = grid.getAt(row);
*/
showInfo(record);
}
}
イベント処理はこれだけです。イベントの引数にそれぞれ、grid,row,eを当てています。ダブルクリックした対象のrecordをストアから取得して、そのレコードをshowInfo()で処理しています。showinfo()は詳細をポップアップで表示する処理です。grid.getStore()でストアを取得して、getAt()でレコードを取得します。showInfo()関数は前回のサンプルでtbarのハンドラーに仕込んだ処理と全く同じです。
意外と簡単ですね。次にrowcontextmenuのイベントを処理します。
ExtJSでは独自の右クリックメニュー(コンテクストメニュー)を設定することができます。基本的な考え方としてはExtのMenuクラス(Ext.menu.Menuクラス等)を右クリックした位置に表示して、ブラウザの右クリックメニューをキャンセルさせることで、ExtJSで独自の右クリックメニューを表示させています。
rowdblclickと同じでrowcontextmenuも基本的にストアからrecordを取り出すことが目標です。
処理の大まかな流れは
1.右クリックした行を選択する。
↓
2.イベントを止める
↓
3.メニューを表示
↓
4.メニューの処理でrecordを取得
になります
実際にサンプルを見ていきます。
listeners:{
rowcontextmenu:function(grid, row, e){
//右クリックでセレクト処理(セレクトしたものを後で右クリックメニューで取得する)
grid.getSelectionModel().selectRow(row);
//右クリックイベントを止める。ここで止めないとブラウザの右クリックメニューが表示されてしまう。
e.stopEvent();
//コンテクストメニューを表示
contextMenu.showAt(e.getXY());
}
}
コンテクストメニューの処理
var contextMenu = new Ext.menu.Menu({
items: [
{
text:'詳細表示',
iconCls:'info',
scope:this,
handler: function(btn){
var record = grid.selModel.getSelected();
showInfo(record);
}
},{
text:'削除',
iconCls:'delete',
scope:this,
handler:function(btn){
var record = grid.selModel.getSelected();
Ext.Msg.alert('選択中のブラウザの削除', '「' + record.get('name') + '」を削除しますか?');
}
}
]
});
右クリックした行を選択して、その後その行のレコードを取得して処理します。コンテクストメニューの処理は前回のtbarの記述とよく似ています。今回は詳細表示のほかに削除のメニューもつけています。削除の処理はまだダミーでポップアップが表示されるだけです。handlerの中が右クリックの実際の処理ですが、recordをセレクションモデルから取得しています。あとはrowdblclickと同じでshowInfow()に処理を渡しています。削除のほうも処理の内容はほぼ同じです。
これでグリッドの各行に対応した右クリックを表示することができるようになりました。右クリックメニューはさらに階層を使ってアクションを沢山指定することもできます。詳しくはAPIリファセンスを参照してください。
この2つのイベント以外にもグリッドには様々なイベントが定義されています。APIリファレンスのイベントの項目を見て、listenersに設定して試してみるとExtJSグリッドの多機能さが良く分かると思います。また独自のイベントを定義することもできます。イベントについてはまた別の機会に解説します。




[...] ExJS入門22 グリッドのイベント処理(ダブルクリック、右クリック) [...]
ExJS入門28 チェックボックス付きグリッドパネル | ExtJSで楽しくRIA業務アプリ開発
30 4 月 10 at 12:44 PM
[...] ExJS入門22 グリッドのイベント処理(ダブルクリック、右クリック) [...]
ExJS入門29 JSONPを使ってYouTube Data APIをグリッドパネルに読み込む | ExtJSで楽しくRIA業務アプリ開発
7 5 月 10 at 11:48 AM
[...] ExJS入門22 グリッドのイベント処理(ダブルクリック、右クリック) [...]
ExJS入門30 Twitter Search APIを使ったグリッドパネル | ExtJSで楽しくRIA業務アプリ開発
10 5 月 10 at 10:04 AM