ExtJS 3.0を使用したネストグリッド

はじめに





画像



この記事で検討する問題の本質は、ExtJSライブラリのGridオブジェクトがネストのコンテキストでの使用を意図していないことです。 一般的な場合、そのようなタスクが開発者に直面することはめったにありません。 それでも、たとえば、私の場合、対処しなければならないことがあります。 以下では、得られた経験を共有しようとします。そして、おそらく、誰かにかけがえのない助けを提供します。 それでは、幸運を...







ネストされたグリッドまたはColumnTree





多くの人は、ネストされた「グリッド」を実装しようとする代わりに、ほとんどのタスクがColumnTreeメソッドを使用して簡単に解決できることに気付くかもしれません。 はい、そのようなソリューションに完全に満足している場合-それを使用してください。 それがColumnTreesの目的です。 しかし、多くの場合、グリッドが提供するすべての有用な機能、つまり、並べ替え、列のドラッグアンドドロップ、フィルターなどを失うという事実を理解するのは非常に困難です。 など 本当に必要な場合は、あるグリッドを別のグリッドに投資する機会を実装することを検討する必要があります。 以下にその方法を示します。



RowExpanderの使用に関する問題





一見、uxライブラリからRowExpanderプラグインが呼び出されて問題を解決します。 ただし、すべてがそれほど単純ではありません。 このプラグインは、「グリッド」行の任意のHTMLコードを表示/非表示できるように設計されています。 特に、行に別のグリッドを埋め込むときに、このプラグインの操作で問題が発生します。 実際、終了:独自のプラグインを作成するか、既存のプラグインを多少変更します。



プラグインの実装は、多くの自由時間がある人の良心に任せますが、修正パスを選択しました。 最終的に、変更されたプラグインを別の名前で呼び出し、それを新しい独自のプラグインとして使用することを禁止する人はいません。 あなたの健康に! :)



主な整頓は、アイコンの誤った表示と、このプラグインを使用する「グリッド」内にあるRowExpanderプラグインのいくつかの関連する誤った動作に関連しています。 問題を解決するという考え方の本質は、別の「グリッド」にネストされた各「グリッド」が独自のスタイル名を使用して、線の開放/閉鎖を決定する必要があるということです。 このアイデアを武器に、グリッド識別子に直接依存する異なる名前を持つ同一のスタイルを動的に作成するのは非常に簡単です。 これは非常に簡単です。 次のコードを追加して、プラグインコンストラクターを少し変更します。



if (!config.id) {

config.id = Ext.id();

}



Ext.apply( this , config);



var css =

'.x-' + this .id + '-grid3-row-collapsed .x-grid3-row-expander { background-position:0 0; }' +

'.x-' + this .id + '-grid3-row-expanded .x-grid3-row-expander { background-position:-25px 0; }' +

'.x-' + this .id + '-grid3-row-collapsed .x-grid3-row-body { display:none !important; }' +

'.x-' + this .id + '-grid3-row-expanded .x-grid3-row-body { display:block !important; }'

;



Ext.util.CSS.createStyleSheet( css, Ext.id());



this .expanderClass = 'x-grid3-row-expander' ;

this .rowExpandedClass = 'x-' + this .id + '-grid3-row-expanded' ;

this .rowCollapsedClass = 'x-' + this .id + '-grid3-row-collapsed' ;




* This source code was highlighted with Source Code Highlighter .








expanderClass、rowExpandedClass、rowCollapsedClassのプロパティを定義する必要があるのは、プラグイン内で値を操作するのが非常に簡単になり、コードを変更する必要があるためです。



これで、ページ上の一意のグリッドごとに個別のスタイルクラスができました。 プラグインの動作の決定に関連するメソッドを変更して、事前に定義したスタイルを使用できるようにします。



レンダリング方法を変更します。



return '<div class="' + this .expanderClass + '"> </div>' ;



* This source code was highlighted with Source Code Highlighter .








また、toggleRowメソッドを変更します。

this [Ext.fly(row).hasClass( this .rowCollapsedClass) ? 'expandRow' : 'collapseRow' ](row);



* This source code was highlighted with Source Code Highlighter .








expandRow:

Ext.fly( row).replaceClass( this .rowCollapsedClass, this .rowExpandedClass);



* This source code was highlighted with Source Code Highlighter .








そしてcollapseRow:

Ext.fly( row).replaceClass( this .rowExpandedClass, this .rowCollapsedClass);



* This source code was highlighted with Source Code Highlighter .








上記のプラグイン疾患のこの治療に関するすべては完全であると考えることができます。



ただし、これに関するすべての問題に対する完全な解決策はありません。



木の枝と葉





最初に、他のツリーと同様に、「ブランチ」と「リーフ」を適切に反映できる必要があります。 これらの概念により、「ブランチ」を開くことができ(子孫がある)、葉には子孫がないことを意味します。 残念ながら、現在の状態のRowExpanderは、「葉」と「ブランチ」を区別する方法を知らず、「グリッド」のすべての行にオープン/クローズコントロールを追加します。 ツリーを完全に実装するには、引き続き変更する必要があります。



幸いなことに、決定はそれほど複雑ではありません。 データセットには、レコードが最終(「葉」)であるか、子孫(「枝」)を含む可能性があるかの兆候を含めるべきであるというテーゼに焦点を当てましょう。 これを行うには、たとえば、論理値trueまたはfalse(is_leaf = true-"leaf"、is_leaf = false-"branch")をとる "is_leaf"という名前でレコードのフィールドを定義するだけで十分です。



同時に、以前のようにプラグインが動作するのを防ぐべきではありません。 つまり、プラグインがツリーモードで動作する方法とタイミングを決定します。デフォルトでは、以前と同じように動作します。



このようなメカニズムを実装するには、パブリック構成プロパティactAsTree = falseおよびtreeLeafProperty = 'is_leaf'を定義します。 したがって、プラグインの初期化中に、プラグインがツリーのように振る舞うかどうかを示し(実際には、「グリッド」の行がツリーの葉であるかどうかを確認します)、レコードの「シート」属性の名前を個別に指定することもできます。



まず、シートを表示するための別のスタイルを定義する必要があります(実際、is_leaf = trueタイプの要素のopen / close要素を非表示にする必要があります)。



作成済みのスタイル定義に追加します。

var css =

...

+ '.x-grid-expander-leaf .x-grid3-row-expander { background: none; }'

;




* This source code was highlighted with Source Code Highlighter .








このスタイルクラス名のプラグイン内で使用できるプロパティを定義します。

this .leafClass = 'x-grid-expander-leaf' ;



* This source code was highlighted with Source Code Highlighter .








このクラスを対応する行に付加し、リーフとしてマークされた行を開いたり閉じたりするアクションを禁止する必要があります。



これを行うには、getRowClassメソッドを変更します(文字列を初期化します)。

var cssClass = this .state[record.id] ? this .rowExpandedClass : this .rowCollapsedClass;

if ( this .actAsTree && record.get( this .treeLeafProperty)) {

cssClass = this .leafClass;

}

return cssClass;




* This source code was highlighted with Source Code Highlighter .








さらに、メソッドtoggleRow、expandRow、collapseRowにチェックを追加します(葉に対するアクションを禁止します)。

if (Ext.fly(row).hasClass( this .leafClass)) {

return ;

}




* This source code was highlighted with Source Code Highlighter .








イベント処理の問題





結局のところ、問題は残っています。 互いにネストされた「グリッド」の動作はかなり不適切です。 行の選択、並べ替えなどの際に不具合が発生します。 子孫の行に対するアクションは、親の「グリッド」に投影されます。 これはすべて非常に不快ですが、解決するのは非常に簡単です!



新しく作成された各子孫で、ポップアップイベントを無効にするだけです。 これを行うには、RowExpanderでonRenderメソッドに次の変更を行います。このメソッドは、「メッシュ」自体のレンダリング時に実行されます。



if ( this .actAsTree) {

grid.getEl().swallowEvent([ 'mouseover' , 'mouseout' , 'mousedown' , 'click' , 'dblclick' ]);

});




* This source code was highlighted with Source Code Highlighter .








メモリリークの問題





そして、すべての問題が解決されたわけではありません:)。 折りたたまれたグリッドに関連付けられているすべてのコンポーネントを削除する必要があります。 特にこの領域では複数回変更される可能性があるため、詳細な変更を説明することは意味がありません。 コードを見てください:



変更されたRowExpanderプラグインの完全なコード: RowExpander.js

ネストされたグリッドのライブ例: ExtJSネストされたグリッドの例



おわりに





ネストされたグリッドの構築に関する最初の困難にもかかわらず、「グリッド」がネストできないことに直面しているように見えますが、かなり簡単な方法でかなり許容できる結果を達成することができました。



この記事が誰かが困難を克服するのに役立つことを願うばかりです。



開発に頑張ってください!



PSこれは、私の個人ブログに投稿されたオリジナル記事「 ExtJS 3.0を使用したネストされたグリッド 」のクロス投稿です。



All Articles