unoh.github.com

Ext JS 2.0正式版リリース - 1.xから2.0への移行のメモ

Tue Dec 11 02:49:56 -0800 2007

isogawaです。

以前紹介したJavaScriptフレームワークExt JSのメジャーバージョンアップである2.0の正式版が、先週末にリリースされました。

Ext 2.0が提供する機能については、以下のサンプルページをご覧いただくのが手っ取り早いでしょう。

さて、Ext 2.0は従来の1.xから大幅に刷新されており、残念ながら1.xとの互換性は高くありません。おそらく1.x用に書かれたコードの殆どは、そのままでは2.0で動作しないでしょう。以下にマイグレーション用のドキュメントが用意されていますが、かなりの量で、ひと通り目を通すだけでも大変です。

以下では、自分がこれまでに作成した1.x用のコードに対して2.0へのマイグレーションを行ってみた際に気付いた点をまとめてみました。ただし、以下の内容がマイグレーションのすべてを網羅しているわけではなく、また実際のところ、細々とした変更が結構あって、すべて覚えてなかったりするので万全ではない点、ご留意ください(例によって、間違ってるところがあるようでしたら、コメントなどで遠慮なくご指摘ください)。

以下のコードは抜粋です。全ソースは、お手数ですがこちらからダウンロードしてご覧ください。

グリッド

Ext.grid.GridはExt.grid.GridPanelに変更になりました。これは親クラスがObservableからPanelに変更されたためで、単なる名称の変更ではなく、従来のExt.gridとExt.GridPanelが統合されたものになっています。

従って根本的には、1.xのExt.grid.Gridと2.0のExt.grid.GridPanelは別物なのですが、Ext.grid.Gridだけのマイグレーションに限れば、従来との互換性はかなり高く、1.xのコードの多くはわずかな修正で移行できるのではないかと思われます。

以下は、Tutorial:Introduction to Ext 2.0にある非常にシンプルなグリッドの例を、1.1.1と2.0の場合で対比できるように書き直したものです。

Ext 1.1.1

var grid = new Ext.grid.Grid('grid-example', {
  ds: new Ext.data.Store({
    data:   myData,
    reader: myReader
  }),
  cm: new Ext.grid.ColumnModel([
    {header: 'Company',   width: 120, sortable: true, dataIndex: 'company', id: 'company'},
    {header: 'Price',     width:  90, sortable: true, dataIndex: 'price'},
    {header: 'Change',    width:  90, sortable: true, dataIndex: 'change'},
    {header: '% Change',  width:  90, sortable: true, dataIndex: 'pctChange'},
    {header: 'Updated',   width: 120, sortable: true, dataIndex: 'lastChange', renderer: Ext.util.Format.dateRenderer('m/d/Y')}
  ]),
  autoExpandColumn: 'company'
});
grid.render();

Ext 2.0

var grid = new Ext.grid.GridPanel({
  renderTo: 'grid-example',
  store: new Ext.data.Store({
    data:   myData,
    reader: myReader
  }),
  columns: [
    {header: 'Company',   width: 120, sortable: true, dataIndex: 'company'},
    {header: 'Price',     width:  90, sortable: true, dataIndex: 'price'},
    {header: 'Change',    width:  90, sortable: true, dataIndex: 'change'},
    {header: '% Change',  width:  90, sortable: true, dataIndex: 'pctChange'},
    {header: 'Updated',   width: 120, sortable: true, dataIndex: 'lastChange', renderer: Ext.util.Format.dateRenderer('m/d/Y')}
  ],
  viewConfig: {forceFit: true}
});

グリッドパネルとツールバー

上述の通り、Ext 2.0ではExt.gridとExt.GridPanelがExt.grid.GridPanelに統合されました。Ext 1.xではグリッドをレイアウトに組み込むには、Ext.GridPanelのインスタンスを別途にあらためて作成する必要がありましたが、2.0では、従来Ext.GridPanelに対して行っていた指定を、Ext.grid.GridPanelのコンフィグにまとめられるようになりました。

また、1.xではグリッドパネルにツールバーを組み込むにはそのパネルのヘッダ/フッタを取得し、Ext.Toolbarのインスタンスを作成する必要がありましたが、2.0ではツールバーもtbarコンフィグでまとめて指定できるようになりました。

Ext 1.1.1

var grid = new Ext.grid.Grid('grid-example', {
  // 上のグリッドの例と同じなので省略
  // ...
  autoExpandColumn: 'company'
});
grid.render();

/* Grid Panel and Toolbar */
var gridPanel = new Ext.GridPanel(grid, {title: 'My First Grid'});
var gridPanelToolbar = new Ext.Toolbar(grid.getView().getHeaderPanel(true));
gridPanelToolbar.addButton({
    text: 'Click here to show dialog',
    handler: this.showDialog.createDelegate(this)
});

Ext 2.0

var grid = new Ext.grid.GridPanel({
  // 上のグリッドの例と同じなので省略
  // ...
  viewConfig: {forceFit: true},

  title: 'My First Grid',
  header: false,
  tbar: [{
    text: 'Click here to show dialog',
    handler: this.showDialog.createDelegate(this)
  }]
});

レイアウト

レイアウトは2.0で最も変更の大きいもののひとつで、クラス構造そのものが全面的に変更されています(詳細はExt 1 to 2 Migration Guide - Converting BorderLayout to 2.0をご覧ください)。

東西南北と中央の各リージョンにパネルを配していくというコンセプトは同様ですが、その手順は大きく異なります。

以下の例は、Extの利用例として多く見られる、ブラウザ画面の全体にレイアウトを配置するレイアウトのものです。1.xでは、これはExt.BorderLayoutの描画先にdocument.bodyを指定して行っていましたが、2.0ではExt.BorderLayoutは廃され、こうしたレイアウトを実現する、専用のExt.Viewportクラスが用意されています。

Ext 1.1.1

Ext.state.Manager.setProvider(new Ext.state.CookieProvider());
var layout = new Ext.BorderLayout(document.body, {
  west: {
    title: 'West Panel',
    width: 200,
    split: true,
    collapsible: true,
    autoScroll: true
  },
  center: {
    tabPosition: 'top',
    closeOnTab: true,
    autoScroll: true
  }
});
layout.beginUpdate();
layout.getRegion('west').add(new Ext.ContentPanel('west'));
var center = layout.getRegion('center');
center.add(gridPanel);
center.add(new Ext.ContentPanel('tab', {title: 'Tab', closable: true}));
center.showPanel(gridPanel);
layout.restoreState();
layout.endUpdate();

Ext 2.0

Ext.state.Manager.setProvider(new Ext.state.CookieProvider());
new Ext.Viewport({
  layout: 'border',
  items: [
    {
      region: 'west',
      contentEl: 'west',
      title: 'West Panel',
      width: 200,
      split: true,
      collapsible: true,
      autoScroll: true
    },
    {
      region: 'center',
      xtype: 'tabpanel',
      tabPosition: 'top',
      activeTab: 0,
      items: [
        grid,
        {contentEl: 'tab', title: 'Tab', autoScroll: true, closable: true}
      ]
    }
  ]
});

ダイアログ

Ext 1.xでのExt.BasicDialogやExt.LayoutDialogは2.0では廃され、Ext.Windowクラスに置き換えられました。Ext.Windowクラスは、Ext.Viewportクラスと同様にレイアウト構成などすべてコンフィグで行え、ボタンやキー操作などの定義もすべてコンフィグで行えるようになっています。

Ext 1.1.1

showDialog: function() {
  if (!dialog) {
    dialog = new Ext.LayoutDialog('dialog', {
      title: 'A Dialog',
      modal: true,
      width: 320,
      height: 240,
      shadow: true,
      proxyDrag: true,
      center: {
        tabPosition: 'top',
        closeOnTab: true,
        autoScroll: true
      }
    });
    dialog.addButton('Close', dialog.hide, dialog);
    dialog.addKeyListener(Ext.EventObject.ESC, dialog.hide, dialog);
    var dialogLayout = dialog.getLayout();
    dialogLayout.beginUpdate();
    dialogLayout.add('center', new Ext.ContentPanel('dialog-body', {title: 'Hello', autoScroll: true}));
    dialogLayout.add('center', new Ext.ContentPanel('tab', {title: 'Tab', autoScroll: true, closable: true}));
    dialogLayout.endUpdate();
  }
  dialog.show();
}

Ext 2.0

showDialog: function() {
  if (!dialog) {
    dialog = new Ext.Window({
      applyTo: 'dialog',
      title: 'A Dialog',
      modal: true,
      width: 320,
      height: 240,
      layout: 'fit',
      items: [{
        region: 'center',
        xtype: 'tabpanel',
        tabPosition: 'top',
        activeTab: 0,
        items: [
          {contentEl: 'dialog-body', title: 'Hello', autoScroll: true},
          {contentEl: 'tab', title: 'Tab', autoScroll: true, closable: true}
        ]
      }],
      buttons: [{
        text: 'Close',
        handler: function() {
          dialog.hide();
        }
      }],
      keys: [{
        key: Ext.EventObject.ESC,
        handler: function() {
          dialog.hide();
        }
      }]
    });
  }
  dialog.show();
}