読者です 読者をやめる 読者になる 読者になる

ExtJS EditorGridPanel の TextArea 編集時の高さ

EditorGridPanel で TextArea を使った編集を行う場合、TextArea の高さを編集対象セルに合わせて調整してくれないため、セルの値が空白だったりすると以下のように1行のTextAreaが表示されてしまう。


以下の環境で現象を確認。

この現象を解消するには、以下のように Ext.grid.GridEditor の doAutoSize メソッドをオーバーライドする事になる。(厳密には doAutoSize は Ext.Editor のメソッド)

doAutoSize オーバーライド例
//オリジナルのdoAutoSizeメソッドを退避
Ext.grid.GridEditor.prototype.ori_doAutoSize = Ext.grid.GridEditor.prototype.doAutoSize;
//doAutoSizeのオーバーライド
Ext.override(Ext.grid.GridEditor, {
    doAutoSize: function() {
        if (this.autoSize == 'full') {
            var sz = this.boundEl.getSize();
            //編集対象セルの高さを取得
            var height = this.boundEl.dom.parentNode.clientHeight;
            this.setSize(sz.width, height);
        }
        else {
            //オリジナルのdoAutoSizeメソッドを実行
            Ext.grid.GridEditor.prototype.ori_doAutoSize.apply(this);
        }
    }
});

ここでは、autoSize に 'full' が指定された時に、boundEl(div 要素)の親(td 要素)の高さを使って編集領域のサイズを設定している。boundEl の親を使う点に関しては検討の余地があると思うが、他に適切な高さを取得する方法が見つからなかった。

この処理を組み込んだ全体的なサンプルは以下。

サンプル
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html>
<head>
<link rel="stylesheet" type="text/css" href="../ext-3.0.0/resources/css/ext-all.css" />
<style type="text/css">

.x-grid3-col-title {
    /* テキストを折り返して表示 */
    word-break:  break-all;
    white-space: normal;
}

.x-grid3-col-note {
    /* TextArea での入力内容をそのまま表示
       IE6, 7 では動作しないため、white-space を normal にするしかない
     */
    word-break:  break-all;
    white-space: pre;
}
</style>
<script type="text/javascript" src="../ext-3.0.0/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../ext-3.0.0/ext-all.js"></script>
<script type="text/javascript">

Ext.BLANK_IMAGE_URL = "../ext-3.0.0/resources/images/default/s.gif";

Ext.onReady(function() {
    //オリジナルのdoAutoSizeメソッドを退避
    Ext.grid.GridEditor.prototype.ori_doAutoSize = Ext.grid.GridEditor.prototype.doAutoSize;
    Ext.override(Ext.grid.GridEditor, {
        doAutoSize: function() {
            if (this.autoSize == 'full') {
                var sz = this.boundEl.getSize();
                //編集対象セルの高さを取得
                var height = this.boundEl.dom.parentNode.clientHeight;
                this.setSize(sz.width, height);
            }
            else {
                Ext.grid.GridEditor.prototype.ori_doAutoSize.apply(this);
            }
        }
    });

    var data = [
        ['SproutCore で JAX-RS(Jersey) と連携させる方法', 'なお、実際は SproutCore の sc-build コマンドで生成した \nHTML や JavaScript を Jersey のリソースクラス等と共に WAR ファイル化してデプロイするような流れになると思うが、\n今回はそこまではやらず、\n連携方法を確認するまでに止めている。', '2009/11/26'],
        ['Scala で JAX-RS(JSR-311) - Jersey の場合', '動作確認は Ruby スクリプトで実施してみた。\n(Ruby にした理由は特に無いが、JSON データを POST するのが楽そうだったんで)\nまず、http://localhost:8082/customers/add に Customer の JSON データを POST する処理を実装。\nPOST の際に content-type で application/json を指定する。', '2009/11/15'],
        ['Groovy で MongoDB を使用する', '', '2010/02/10']
    ];

    var store = new Ext.data.SimpleStore({
        fields: [
            {name: 'title'},
            {name: 'note'},
            {name: 'date'}
        ]
    });

    store.loadData(data);

    var grid = new Ext.grid.EditorGridPanel({
        columns: [
            //autoSize に full を指定する事で変更した処理が実施される
            {id: 'title', header: 'Title', sortable: true, 
                dataIndex: 'title', width: 100,
                editor: new Ext.grid.GridEditor(new Ext.form.TextArea(), {autoSize: 'full'})},
            //autoSize に full を指定する事で変更した処理が実施される
            {id: 'note', header: 'Note', sortable: true, 
                dataIndex: 'note', width: 250,
                editor: new Ext.grid.GridEditor(new Ext.form.TextArea(), {autoSize: 'full'})},
            {header: 'Date', sortable: true, dataIndex: 'date', width: 75}
        ],
        store: store,
        renderTo: 'grid-sample',
        width: 450,
        height: 250,
        stripeRows: true
    });
});
</script>
</head>
<body>
<div id="grid-sample"></div>
</body>
</html>

これを実行して編集状態にすると、適切な高さで TextArea が表示されるようになる。