This document is currently in progress (DRAFT status). However, it has enough content that I wanted to
make it available for initial review. Please do not edit or translate yet — add all comments, questions,
etc. to the discussion page. I plan on finalizing and "officially" publishing it for the 2.0 final release,
but it is open now for public comment and technical review. —Brian
Welcome to Ext 2.0. If you are new to Ext (or just new to 2.0), you'll probably want to begin with the Ext 2.0 Overview is
it introduces some of the new concepts in version 2.0. This document is intended for existing Ext 1.x users who need to
migrate existing code from 1.x to 2.0. Unfortunately, because of the architectural changes in the new version of Ext, i
t was not possible to maintain full backwards compatibility. While the Overview will help get you oriented with the new
code base, this guide will provide the practical steps needed to migrate your code as painlessly as possible.
Once your application is compiling again under 2.0, you'll probably want to dive into the details and start utilizing some
of the new advances in the framework that could help take your applications to the next level. For additional information
on 2.0, here are some helpful resources:
Here's a high-level summary of all the areas in 2.0 that are not backwards-compatible with 1.x and will require manual modifications to existing code to migrate it to 2.0. Please note that there have been countless minor improvements, bug fixes and other backwards-compatible changes across the framework from 1.x to 2.0. It would be impossible to list everything, so this migration guide is focused only on the areas in the framework that will not work correctly "out of the box" after an upgrade to the 2.0 library. Each item is explained in complete detail in the sections following this summary.
Many classes that did not extend Component in 1.x now do in 2.0. Any 1.x classes that used to pass a container
reference (or any other arguments) and a config into the constructor now render under the Component model,
which means the constructor only takes a config. Because of this, any existing code that creates instances of
classes that now extend Component will most likely need to be changed as follows:
myComponent.render('containerId');
.In 1.x the layout classes were entirely focused around the BorderLayout model. BorderLayout extended the base LayoutManager
, but every other class either extended or was aggregated by BorderLayout. The basic model in 1.x was that a BorderLayout could
contain regions, and regions could contain content panels.
In 2.0, there are several major differences, and understanding them will definitely aid in transitioning existing code from 1.x.
This section will outline how the layout classes generally map between 1.x and 2.0. Note that the mapping is not perfect
as the entire structure was completely rewritten, but it should still give a good sense for where to look in 2.0 for comparable functionality from 1.x.
Ext.LayoutManager | — | LayoutManager didn't actually do much by itself. As a base class, it mostly provided template and proxy functionality that was intended to be useful to its subclasses, such as begin/endUpdate to allow the developer to tell the layout when to render, proxying region event firing at the layout level, view size monitoring and an empty layout template method. The closest match in 2.0 would probably be ContainerLayout, although there isn't much practical similarity in the code. |
Ext.BorderLayout | Ext.layout.BorderLayout, Ext.Container |
In 2.0, the layout classes only provide layout logic, and that's it. Also, they are not generally created directly — instead, they are called and managed internally by the Container classes. So in terms of layout logic, Ext.BorderLayout.layout maps pretty closely to Ext.layout.BorderLayout.onLayout, but in 1.x it was called directly by the developer, while in 2.0 it is called internally by Containers automatically. The functionality of adding panels has been moved to the Container classed in 2.0, and the functionality to add regions is still in BorderLayout, but it no longer contains methods to do so. Instead, now adding regions is done entirely through configuration. |
Ext.ReaderLayout | — | This was simply a convenience class that created a specific BorderLayout configuration to render a classic, 5-pane application. It consisted of a header, a primary center region containing two nested regions (a top one for a list view and one for item preview below), and regions on either side for additional content. There is no corresponding class in 2.0, although the example below of converting a BorderLayout to 2.0 is extremely close to the default ReaderLayout and should provide a perfect template for duplicating that layout style in 2.0 if needed. |
Ext.BasicLayoutRegion, Ext.LayoutRegion |
Ext.layout.BorderLayout.Region | Although not all of the functionality is the same, the two 1.x region classes combined map exactly to the Region class in 2.0. One thing to note is that in 1.x, the regions had a convenient shortcut built-in that adding multiple panels automatically converted each panel into a tab and the region itself became a tab container. In 2.0, Containers can now commonly contain multiple non-tab panels depending on the layout style, so in order to create a set of tabs in 2.0, the TabPanel widget must be used directly (and can of course be added to a BorderLayout region). |
Ext.SplitLayoutRegion | Ext.layout.BorderLayout.SplitRegion | Although not all of the functionality is the same, this is a one-to-one class mapping. |
Ext.ContentPanel, Ext.NestedContentPanel |
Ext.Panel | The Panel class in 2.0 is basically the same as the 1.x ContentPanel although many times more powerful. The NestedContentPanel was specifically available to allow nesting of additional BorderLayouts within an existing ContentPanel. In 2.0, this behavior is already built into the Container/Panel classes to allow arbitrary nesting with any layout, so no extra class is needed. |
Ext.GridPanel | Ext.GridPanel | These classes map exactly, although in 1.x GridPanel was just a wrapper for the grid, while in 2.0 the GridPanel actually is the grid. |
— | AbsoluteLayout, AccordianLayout, AnchorLayout, CardLayout, ColumnLayout, ContainerLayout, FitLayout, FormLayout, TableLayout |
These are all of the new layout managers provided in 2.0. There was nothing comparable in 1.x. |
Now that you should have a good overall understanding of how the layout architecture has changed, an example will provide
the best practical demonstration of transitioning a 1.x BorderLayout to 2.0. In the Ext "\examples\layout\" folder that comes with
the download, there is a file called complex.html. This file existed in 1.x, and has been upgraded to work under 2.0.
Comparing both versions of that file demonstrates how to
upgrade a layout to 2.0, so let's break it down piece by piece.
In 1.x, the BorderLayout was created directly and rendered to document.body. In 2.0, while you can technically
create a Panel rendered and sized to document.body, the Viewport class was built to provide that exact functionality.
Anytime you are rendering a full-screen UI, the Viewport should be the foundation. The Viewport, just like all Container
classes, can support any valid layout style. In this case, we will specify layout:'border'
.
layout = new Ext.BorderLayout(document.body, { |
var viewport = new Ext.Viewport({ |
In 1.x, each object had to be created explicitly and added to its parent explicitly. In 2.0, every Container class has an
items config that can be populated with an array of any Components or other Containers. In this example, every single
object making up the UI has been added in the Viewport's items array.
layout.add('north', new Ext.ContentPanel('north', 'North')); |
items:[ |
As shown above, Regions and ContentPanels were created explicitly as objects in 1.x. While you can still create your
own Regions and Panels in 2.0, the preferred syntax for building a UI is the config syntax shown in the example code.
Each object being passed into the items array is a config object representing a Panel (except the first one, which
shows an example of adding a raw BoxComponent when
a full Panel is not required).
In the 1.x example, tabs are created simply by adding multiple content panels to the same region (as in the
east and center regions). In the 2.0 code, note that TabPanels are explicitly created and added into the items
arrays of the appropriate containers. Note that when specific components are added directly to a layout (as in
the case of the center TabPanel) the region config must be specified on that component.
layout.add('center', new Ext.ContentPanel('center1', |
new Ext.TabPanel({ |
Once everything is constructed, it gets rendered. In 1.x, the developer was responsible for telling the layout
when to defer rendering and when to update the UI using beginUpdate/endUpdate. In 2.0, this is no longer
required. You simply build up the UI and updates are automatically deferred. Then once the top-most container
is rendered, all contained components get rendered automatically by the framework. For regular Panels, this
would require a call at the end like panel.render(document.body)
. However, since Viewports are automatically
rendered for you, this is not needed in this example.
The underlying models for getting data into a grid (proxies, readers, stores, column model, selection model) have
not changed significantly in 2.0, which is good news for upgrading grids. The biggest change is that Grid extended
Observable, but in 2.0, it now extends Panel (hence, the name change to GridPanel). While there are some breaking
changes as detailed below, most are relatively minor. However, there are a huge number of new members in GridPanel,
so be sure to have a look through the API docs to see how much more powerful the grid is in 2.0.
Config Options | ||
enableColLock | — | Column locking has been removed in 2.0 Additional details |
enableCtxMenu | enableHdMenu | In 1.x, the header menu was only accessible via context (right-click) menu. In 2.0, the menu dropdown arrows are rendered into the header directly and automatically displayed on mouseover. Because of this the 1.x name for this event was updated to reflect the new meaning. |
autoSizeColumns | autoFill (GridView) | This option was renamed and moved to GridView (pass in the GridPanel's viewConfig option). |
autoSizeHeaders | — | This is no longer needed in 2.0 as the header widths are automatically synced. |
enableRowHeightSync | — | Related to column locking which is no longer supported in 2.0. Additional details |
Methods | ||
Grid(container, config) | GridPanel(config) | Renamed to reflect the new inheritance hierarchy. For additional information on upgrading the constructor, see the Component constructor upgrade guidelines. |
autoSize | doLayout | The method of redrawing the grid now comes from the base Container class in 2.0. |
getDataSource | getStore | Method renamed for consistency. |
getGridEl | getEl | This method now comes from the base Component class. |
render() | render([container], [position]) | This method is backwards-compatible, but is still worth mentioning for its new optional arguments. It is now inherited from the base Component class for consistent rendering support along with other components. |
Events | ||
dragdrop, dragenter, dragout, dragover, enddrag, startdrag |
— | These never actually fired in 1.x and have been removed. |
Methods | ||
autoSizeColumn | — | Autosizing (or force-fitting in 2.0) is no longer supported on a per column basis. |
autoSizeColumns | forceFit [config] | A method call is no longer needed. Just pass forceFit in the grid's viewConfig and it will automatically maintain its fit after each column resize. |
ensureVisible | focusCell/focusRow | This method was made private as focusCell or focusRow should be called instead. Focusing a cell or row will automatically scroll it into view if needed. |
fitColumns | forceFit [config] | A method call is no longer needed. Just pass forceFit in the grid's viewConfig and it will automatically maintain its fit after each column resize. |
getFooterPanel | bbar (GridPanel) | The GridView no longer maintains its own separate footer for toolbars and other components. The containing GridPanel already contains a bottom bar (bbar) for this purpose. |
getHeaderPanel | tbar (GridPanel) | The GridView no longer maintains its own separate header for toolbars and other components. The containing GridPanel already contains a top bar (tbar) for this purpose. |
The column locking feature in the 1.x grid (locking one or more columns in place so that columns to the right could
scroll horizontally leaving the locked columns in place) has been removed permanently. The header menu option
for locking/unlocking has been removed, and no configs or methods related to locking are available in 2.0.
Column locking was a great feature for a small subset of Ext users. However, because of the underlying layout and
rendering requirements necessary to enable locking, grid performance was significantly affected for everyone.
Unfortunately, column locking is fundamentally incompatible with high performance in a web environment, and
performance has always been a high priority for Ext. Because of that, we made the decision to remove it with the
result that the grid in 2.0 renders much faster and can handle many more rows of data than it did in 1.x.
The API for TabPanel has received a major upgrade in 2.0 as it now extends Panel instead of Observable. It also conta
ins standard Panel objects as tabs rather than the special TabPanelItem class that existed in 1.x. While there are some
breaking changes as detailed below, most are relatively minor. However, there are a huge number of new members in
TabPanel, so be sure to have a look through the API docs to see how much more powerful the tabs are in 2.0.
Here is a simple example of upgrading a basic TabPanel from 1.x to 2.0. Using the API reference below you should be
able to handle any additional member conversions that may be needed. Note that while the JS code is a little bit shorter
in 1.x, the overall complexity is actually reduced in 2.0 thanks to the greater config flexibility. No more need for custom
CSS for basic styling tasks.
// CSS: |
var tabs = new Ext.TabPanel({ |
Config Options | ||
currentTabWidth, maxTabWidth, preferredTabWidth |
— | In 1.x, all of these tab width configs only applied if the resizeTabs config was true. In that case, Ext managed tab widths within the rules applied by these additional configs. In 2.0 the reizeTabs config is still available, but tab widths are completely managed and these additional options are no longer honored. Only minWidth still applies in this case. |
Methods | ||
TabPanel(container, config) | TabPanel(config) | TabPanel now extends Panel instead of Observable. For additional information on upgrading the constructor, see the Component constructor upgrade guidelines. |
addTab, addTabItem |
add (Container) | Both addTab (for creating new TabPanelItems) and addTabItem (for adding existing ones) are replaced by the inherited Container add method that expects a Panel. For an approximation of addTab, you can pass in a new Panel config and it will be created dynamically on render. |
autoSizeTabs | — | This is now an internal method and should not be called directly as tab widths are automatically managed by Ext. |
disableTab, enableTab |
— | In 1.x, these methods delegated to a contained TabPanelItem's disable/enable methods. In 2.0, there are no methods on the TabPanel to directly disable/enable a tab. Instead you would simply get a tab (Panel) reference and act on it directly. For example: tabPanel.getItem('my-tab').enable(); |
getActiveTab : TabPanelItem | getActiveTab : Panel | This method is the same, but it is worth noting that the object returned is now different, so the actions performed on the returned object may have to be updated as well. |
getCount | items.length | In 2.0, the Container items collections is exposed directly as a property that can be used to access the contained items in many ways. |
getTab : TabPanelItem | getItem : Panel | This getter is now an inherited Component method that returns a Panel object instead of a TabPanelItem. |
hideTab, unhideTab |
hideTabStripItem, unhideTabStripItem |
|
removeTab | remove (Container) | This is now an inherited Container method. |
setTabWidth | — | You can set the tab width initially using the tabWidth config, but the setTabWidth method is no longer available. |
syncHeight([height]) | — | Tab dimensions are now managed by the container automatically. |
Properties | ||
bodyEl | body | Since TabPanel is now a subclass of Panel, the standard Panel body replaces bodyEl. |
el | getEl() | In 2.0, el is private and the inherited Component getEl method should be used instead. |
Note that while the TabPanelItem events are all supported by Panel, event handlers will now be called with a Panel object instead of a
TabPanelItem, so any handling logic might have to change accordingly.
Properties | ||
TabPanelItem(tabPanel, id, text, closable) | see notes | TabPanelItems in 1.x only existed for the purpose of residing in a TabPanel, thus they had a very specific constructor argument list. There is no direct replacement as Panels are generic and the constructor is config-based. However, the following code would be equivalent when adding a new Panel to a TabPanel (note that a separate container config is not needed in this example since the Panel is being directly added):tabPanel.add(new Ext.Panel({ |
bodyEl | body | |
closeText | — | The tab's close button no longer supports configurable tooltip text in 2.0. |
id | getId() | The id property is now private in 2.0 and the inherited Component getId method should be used instead. |
tabPanel | ownerCt | Every Component in 2.0 supports the ownerCt property which returns a reference to the owning Container. |
Methods | ||
activate | show (Component) | When a Panel is added into a TabPanel as a tab, its normal show method will activate it within the TabPanel. |
getText | title [property] | The standard Panel title is used as the tab text when the Panel is added to a TabPanel. |
getUpdateManager | getUpdater | This returns the update manager for the Panel's body element. |
isActive | — | Panels have no knowledge of whether or not they are active. Instead you could check tabPanel.getActiveTab().getId() == 'my-panel' . |
isHidden | hidden [property] | The standard Component hidden property can be used so no method is necessary. |
refresh, setUrl |
load, getUpdater().refresh |
In 1.x, refresh used the properties set in setUrl to reload remote content into the tab. In 2.0, Panels can be loaded directly using the load method, or you can access the update manager directly via getUpdater and either load the Panel or refresh it using previously loaded configuration data. |
setContent | body.update | Equiv |