Ext JSデータグリッドのカスタマイズ: セル、レンダラー、エディター
Ext JSのデータグリッドは、エンタープライズアプリケーションで利用可能な、最も機能豊富で強力なJavaScriptグリッドコンポーネントの一つとして広く認知されています。データ集約型のユーザーインターフェイスを構築する開発者にとって、グリッドセル、レンダラー(ハンドラー)、エディターのカスタマイズ方法をしっかりと理解することは不可欠です。

これらの機能により、生データを意味のある視覚的表現に変換し、インプレースでの編集を可能にすることで、ユーザーエクスペリエンスの向上、大規模データセットのパフォーマンス最適化を実現できます。
この記事では、Ext JSのデータグリッドアーキテクチャの構造概要を紹介し、以下の操作に関してその手順を詳細に解説します。
- データマッピングとカラムの基礎
- Modernツールキットのセル構成
- レンダラー/ハンドラーによる外観の変更
- インラインエディターと編集プラグイン
- 高度なインタラクションを実現するウィジェットセル
- 大規模グリッドのパフォーマンス ベストプラクティス
Ext JSグリッドのアーキテクチャとデータフロー
Ext JSのグリッドは、MVCに似たパターンに従って、その個々の役割を明確に分離して構築されています。このアーキテクチャを理解することが、効果的なカスタマイズを行うためのベースとなります。
ストア
ストアは、グリッドで使用されるレコードのコレクションを管理します。ストアは以下の処理を行います。
- データの読み込み(例:AJAX、REST、またはインメモリデータを経由)
- 並べ替えとフィルタリング
- ページング
- 変更内容のサーバーへの同期(設定時)
グリッドコンポーネントはストアを監視します。ストアが変更されると(レコードの更新、挿入、削除時)
、グリッドビューも自動的に更新されます。
モデル
ストア内の各レコードはモデルによって定義されます。モデルは以下の内容を記述します。
- フィールドとそのデータ型(例:string、int、float、date、booleanなど)
- 検証ルール
- 変換/正規化ロジックなど(オプション)
グリッド内のカラム定義は通常、モデルフィールドに直接マッピングされます。正確なマッピングは、データを正しく表示する上で不可欠です。
グリッドパネル
グリッドパネル (あるいは単純に「グリッド(Grid)」) は、データを視覚的に表現したものです。
- ストアのレコードを使用して行と列をレンダリング
- 選択、スクロール、カラムのサイズ変更、カラムメニューなどを管理
- ストアの現在の状態を反映(データそのものは保存しない)
データの永続化と自動同期
Ext JSはフロントエンドフレームワークであり、編集内容を自動的にサーバーに保持することはありません。デフォルトの動作は以下のとおりです。
- セルを編集すると、ストアのレコードがすぐに更新されます
- これらの変更を自動的に保存するには、次のようにストアを構成する必要があります
autoSync: true
autoSync: true に設定していると、レコードが変更されるたびに、指定したプロキシ(REST、AJAXなど)によってバックエンドAPIに更新内容が送信されます。あるいは、store.sync() を呼び出すことで、手動で同期を制御することもできます。
データマッピングとカラムの基礎
カラム(列)は、グリッド内のセルの動作の主な構成ポイントです。
dataIndex: キーマッピング
このように記述されるdataIndexは、グリッドカラムにとって最も重要な設定です。これにより、どのモデルフィールドがそのカラムにバインドされるかを定義します。
{
text: 'Price',
dataIndex: 'price'
}
主なルールは以下のとおりです。
- dataIndex はモデルで定義されたフィールド名と一致する必要があります
- 一致しない場合は、セルは空で表示されます(カスタムレンダラー/ハンドラーを用いるかテンプレートを使用してコンテンツを生成する場合を除く)
- レンダラーとエディターは通常、 dataIndex を介して解決された値を操作します
フィールドに直接マップされない列(計算フィールドなど)が必要な場合は、次のいずれかを実行します。
- dataIndex を無視してレコードから表示値を構築するレンダラー/ハンドラーを使用
- モデルフィールドでconvert 関数を使用して、仮想フィールドを事前に計算
Modernツールキットのセル構成
Modernツールキットでは、各カラムでセル構成を定義できます。これはModernツールキット独自の強力な機能で、カラム内で直接セルコンポーネントを構成できます。
基本的なセルの使用法
例:
{
text: 'Name',
dataIndex: 'name',
cell: {
userCls: 'name-cell',
encodeHtml: true
}
}
主なプロパティ:
- userCls – スタイル設定のためにセルのコンポーネントにカスタムCSSクラスを追加
- encodeHtml – trueでHTMLをエンコード(デフォルト)。falseで生のHTMLをレンダリング
このアプローチにより、ほとんどの視覚的なカスタマイズ事項をセル内に保持できるため、カラム定義をクリーンかつ宣言的に維持できます。
生のHTMLレンダリング
レンダラー/ハンドラーが HTML(アイコン、リッチフォーマットなど)を返す場合は、encodeHtml が適切に設定されている必要があります。
{
text: 'Status',
dataIndex: 'status',
renderer: 'statusRenderer',
cell: {
encodeHtml: false,
userCls: 'status-cell'
}
}
HTMLエンコードを無効にすると、グリッドはレンダラーの出力をHTMLとして信頼するようになります。これはアイコンフォントやマークアップベースの書式設定を行うのに便利です。
レンダラー/ハンドラーによる外観の変更
レンダラー(この文脈では「ハンドラー」とも呼びます)は、データを表示用に変換するために用います。レンダラーは、ベースとなるストアレコードを変更することはありません。ClassicツールキットとModernツールキットのどちらもレンダラーをサポートしていますが、シグネチャが異なります。
一般的な使用例
レンダラーの一般的なシナリオは以下のとおりです。
- 値の書式設定
- 例:数値を通貨として書式化:$1,234.56
- 日付、パーセントなどの書式設定
- アイコン/フラグ変換
- 論理型(bool)をアイコン(チェックマーク、バツマークなど)にマッピング
- 状態フラグ、矢印、またはトレンドインジケーターを表示
- 条件付きスタイル
- しきい値に基づいて異なる色またはクラスを適用
- 負の値を赤で強調表示
Classicツールキットのレンダラーシグネチャ
Classicツールキットでは、次のようにレンダラーを記述します。
{
text: 'Price',
dataIndex: 'price',
renderer: function (value, metadata, record) {
if (value < 0) {
metadata.style = 'color:red;';
}
return Ext.util.Format.currency(value, '$', 2);
}
}
レンダラーには、以下のパラメータが渡されます。
- value – このセルのフィールド値
- metadata – CSSスタイルとクラスを設定するオブジェクト(例: style、tdCls)
- record – 完全なデータレコード
Classicでの動的なスタイル設定には、metadata.style、metadata.tdCls、またはmetadata.tdAttrを使用できます。
Modernツールキットのレンダラーシグネチャ
Modernツールキットでは、レンダラーによってセルコンポーネントへの直接アクセスが可能です。
{
text: 'Price',
dataIndex: 'price',
renderer: function (value, record, dataIndex, cell, column) {
if (value > 100) {
cell.setCls('high-value-cell');
} else {
cell.setCls('normal-value-cell');
}
return Ext.util.Format.currency(value, '$', 2);
}
}
レンダラーには、以下のパラメータが渡されます。
- value – フィールド値
- record – 関連付けられたレコード
- dataIndex – フィールド名
- cell – セルコンポーネント(Modernのみ)
- column – カラム定義
cellコンポーネントを使用すると、次のことが可能になります。
- cell.setCls()を呼び出してセルのクラスを置換/li>
- インクリメンタルスタイル設定には、cell.addCls() / cell.removeCls()を使用/li>
- 必要に応じて他のセルプロパティを構成
これは、Classicツールキットのmetadataパターンに代わる、Modernツールキットにおける動的なスタイル設定で推奨されるアプローチです。
インラインエディターと編集プラグイン
Ext JSでは、プラグインによって豊富なグリッド内編集機能を提供しています。エディターを用いれば、グリッドのセルや行内で直接データを変更することができるため、ワークフロー効率の向上を図ることができます。
セル編集プラグイン
セル編集プラグインを使用すると、セル単位の編集が可能になります。ClassicツールキットとModernツールキットの双方で設定できます。
例(概念的な例):
plugins: {
cellediting: {
clicksToEdit: 1
}
},
columns: [
{
text: 'Name',
dataIndex: 'name',
editor: {
xtype: 'textfield',
allowBlank: false
}
},
{
text: 'Price',
dataIndex: 'price',
editor: {
xtype: 'numberfield',
minValue: 0
}
}
]
以下に挙げたようなエディターがサポートされています。
- textfield
- numberfield
- datefield
- combobox / selectfield
- ツールキットごとにその他のフォームフィールドを提供
エディターの自動選択
カラムに対して、明示的にエディターを定義していないと、Ext JSは多くのケースで、モデルのフィールドタイプに基づいて適切なエディターを推測します。以下はその例です。
- float型として指定されたフィールドでは、自動的にnumberfieldを使用
- 日付フィールドでは適切な日付ピッカーを使用
この「自動エディター」の動作により開発をスピードアップできる一方で、明示的な構成によって完全な制御が可能になります。
platformConfigを使用したレスポンシブ エディター(Modernツールキット)
Modernツールキットでは、エディターをさまざまなデバイスに適応させるため、platformConfigを用意しています。
editor: {
xtype: 'textfield',
label: 'Name',
platformConfig: {
desktop: {
ui: 'outline'
},
phone: {
ui: 'solo'
}
}
}
platformConfigを用いれば、以下が可能になります。
- デスクトップ(desktop)、タブレット(tablet)、またはスマートフォン(phone)ごとにレイアウト、UI、または動作を調整
- 小さな画面 (コンパクトUI、フルスクリーンオーバーレイなど) 向けに編集エクスペリエンスを最適化
- この適応パターンをエディターだけでなく、ほぼすべてのModernツールキットコンポーネントに適用可能
その他の編集プラグイン
セル編集の他に、Ext JSでは次の機能も提供します。
- 行編集プラグイン
- 多くの場合、インライン行フォームを介して、行内のすべてのフィールドを一度に編集できます
- グリッド編集可能プラグイン(Modernツールキット)
- モバイルデバイス(タブレット/スマートフォン)向けに最適化
- 通常、選択したレコードを編集するためのフローティングフォームまたは全画面フォームを表示
ユーザーエクスペリエンス要件やターゲットプラットフォームに基づいて、これらのプラグインを選択します。
高度なインタラクションを実現するウィジェットセル
高度なシナリオでは、ウィジェットセルを使用することで、グリッドセル内にExt JSコンポーネントを直接埋め込むことができます。これは、単なるテキストやアイコン表示だけでは要件を満たせない場合に特に便利です。
一般的な用途
ウィジェットセルは、以下のようなケースで有用です。
- アクションボタン(例:「表示」、「編集」、「削除」)
- タスクの進捗状況を示すプログレスバー
- グリッド内で直接数値を調整するためのスライダー
- 傾向やパターンを可視的に把握できるスパークラインチャート
Modernツールキットのウィジェットセル
Modernツールキットのウィジェットセルは、軽量かつ高性能な設計が施されており、次のような利点があります。
- 最適化されたコンポーネントの再利用
- 古いウィジェット実装よりも削減されたメモリ使用量
- 簡素化された構成
ウィジェットはデータバインディングを使用して、そのプロパティ値をレコードに結び付けることができます。
- レコードフィールドにvalue、hidden、disabled、textをバインド
- トリガーハンドラーにより、ウィジェットから直接レコードを更新
例えば、セル内のスライダーは数値フィールドのエディターとしてもそのまま機能するため、セルをダブルクリックするなどの別の編集開始操作を行う必要がなくなります。
パフォーマンス最適化のベストプラクティス
セル、レンダラー、エディターをカスタマイズすることで、グリッドでは追加の処理が発生する可能性があります。大規模なデータセットの場合、こうした影響を考慮してパフォーマンスを慎重に管理する必要があります。
コンポーネントのリサイクル(Modernツールキット)
Modernツールキットでは、グリッドはコンポーネントのリサイクルを使用します。
- 表示されているセルごとに新しいコンポーネントを作成するのではなく、スクロールすることでセルコンポーネントが再利用される
- そのため、同じコンポーネントインスタンスが時間の経過とともに異なるレコードを表す場合がある
このことにより、以下のような点に注意する必要があります。
- レコード固有の状態をセルのDOM要素またはコンポーネントに直接保存しない(レコード間で誤って保持されるような方法を取らない)
- レンダラーまたはバインディングに渡されるvalueおよびrecordパラメータによってのみ、スタイルや状態を取得する
このリサイクルメカニズムは、何千ものレコードを効率的にレンダリングするための鍵となります。
テンプレート(class=”cs-c-green”>tpl)とレンダラー関数
HTMLフォーマットのみを必要とするユースケース(複雑なロジックなし)においては、テンプレート(tpl) を使用することで、レンダラー関数よりも高速になる場合があります。
- tplの使用により、セルごとにJavaScript関数を呼び出すオーバーヘッドを回避
- 単純なデータの置換や基本的な条件付きマークアップの場合、テンプレートが最適
{
text: 'Name',
dataIndex: 'name',
tpl: '{name}'
}
簡単な書式化を行う場合、tplを用いるようにします。複雑なロジック、条件付きコンポーネント構成、あるいはセルコンポーネントとのやり取りが必要な場合は、レンダラー/ハンドラーを選択します。
ウィジェットセルを軽量に保つ
ウィジェットセルは強力ですが、過度に使用したり複雑すぎるとコストが高くなる可能性があります。
- ウィジェットセル内では、深くネストされたレイアウトを避ける
- ボタン、スライダー、コンパクトグラフなど、シンプルで単一目的のコンポーネントを使う
- インタラクティブ性が本当に価値を付加する場合にのみウィジェットを使用する
軽量なウィジェットを設計し、その使用を重要なカラムに限定することで、大量のデータでもグリッドはスムーズなスクロールと操作を維持することができます。
まとめ
Ext JSデータグリッドのカスタマイズは、階層化された役割分担の視点で理解する必要があります。
- ストア – データを管理、保存するエンジン
- モデル – レコードの形状を定義するスキーマと検証レイヤー
- グリッドパネル – データを行と列にレンダリングするビュー
- カラムとデータインデックス – データフィールドと表示されるセル間のマッピング
- レンダラー/ハンドラー – 元のデータに触れることなく、値の表示方法を変更する変換レイヤー
- エディターと編集プラグイン – ユーザーがその場でデータを変更できるようにするインタラクション レイヤー
- ウィジェットセル – 豊富なコンポーネントをグリッド行に埋め込む高度なインタラクションレイヤー
- パフォーマンステクニック – 負荷が高い場合でもグリッドの応答性を維持するための手法
セル、レンダラー、エディターを習得し、ここで紹介したパフォーマンスのベストプラクティスを適用することで、Ext JSのデータグリッドを最大限に活用し、デスクトッププラットフォームとモバイルプラットフォームの双方で、堅牢かつインタラクティブで高度にカスタマイズされたデータエクスペリエンスを提供できます。
Ext JSを用いて構築された大規模アプリケーションのアップグレードは、開発チームにとって大きな課題となり得ます。この記事では、Ext JSアプリケーションを最新の状態に維持していくべき理由、アップグレードプロセスにおける一般的な障害、そしてリスクを最小限に抑え、貴重な開発時間を節約するための重要なツール「Ext JS Upgrade Adviser」について解説します。
Senchaチームは、開発をスピードアップし、メンテナンス性の向上、優れたユーザーエクスペリエンスの構築を容易にするSencha Rapid Ext JSの新リリース「Rapid Ext JS 1.1.1」を発表しました。
Senchaチームは、開発をスピードアップし、メンテナンス性の向上、優れたユーザーエクスペリエンスの構築を容易にするSencha Ext JSの最新バージョンExt JS 7.9とRapid Ext JS 1.1を発表しました。