Introduction
This guide walks through the most important changes and their potential impact on updating your Touch applications to the Ext JS modern toolkit. There are many changes due to the modern toolkit sharing the core package, where Touch did not. If you have used Ext JS 5+, you’ll probably be familiar with most of the items in this guide.
If you are new to the Ext JS side of Sencha, you may want to review our notable additions in Ext JS 5 as many of these will apply to the modern toolkit in Ext JS 6. In particular the additions and improvements to the core and charts packages are most likely relevant.
Sencha Cmd Upgrade Process
The first step in the upgrade process is to upgrade the ".sencha"
folder and other key parts of your application. Run sencha app upgrade
from your application root folder:
sencha app upgrade ../path/to/ext6
Alternatively, you can generate a stock modern app and replace its "app"
folder with your own:
sencha -sdk path/to/ext6 generate app --modern YourAppName ./AppFolder
Note: Be sure to use your Touch application’s App Name in place of YourAppName
above.
Browser Support
The following browsers are supported by the modern toolkit.
Desktop
- IE11+
- Firefox and Firefox ESR (Latest Versions)
- Chrome (Latest Versions)
- Safari 7+
Mobile
- IE11+
- Safari 7+
- Android 4.0+ Chrome
- Android 4.4+ Native
Adding DOCTYPE and Meta Tags
We recommend the usage of the HTML5 doctype. We also recommend the X-UA-Compatible meta tag to ensure Internet Explorer does not activate “Compatibility Mode”. The viewport meta tag is necessary for mobile devices to prevent viewport zooming from interfering with the framework’s gesture recognition.
For example:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
Omitting these tags may result in strange behavior and, potentially, a non-functioning application.
Distribution
There is now a Sencha Cmd package named “ext” which contains the framework.
The move to being a package means the build outputs are stored in a “build” folder. This folder is useful if you want to use Ext JS directly without Sencha Cmd.
The “packages” and “src” folders are used by Sencha Cmd applications to build only what your application requires.
{theme}.js / {theme}.css
Themes may contain JavaScript overrides to tune default configs for some components. Generally, you’ll need a script tag following “ext*.js” in order to include the JavaScript portion of a theme:
build/modern/{theme}/{theme}(-debug).js
The -debug
token is optional and, when present, selects the uncompressed JavaScript build of the theme overrides.
The compiled theme files are now present in the following folder off the root of the distribution:
build/modern/{theme}/resources/{theme}-all(-debug).css
Ext.ux
“User Extensions” are provided as a starting point in building useful components. They are often useable as-is, but are intended to serve as examples of how to go beyond the core framework. The “ux” content is basically the same as before but has been converted into an “ux” package. Add “ux” the “requires” array in "app.json"
. If you are not using Sencha Cmd, then you’ll need to add the build outputs of the “ux” package found here:
build/packages/ux/modern/ux(-debug).js
build/packages/ux/modern/modern-neptune/resources/ux-all.css
The “ux” package only builds using the theme-neptune
in the modern toolkit because it is not sensitive to theme changes.
Element
Ext.dom.Helper
There is a minor change in DomHelper behavior with regards to generating HTML markup. For element attributes whose values are undefined
, no attribute markup will be generated. When a valueless attribute is desired, use an empty string instead:
el.createChild({
tag: 'div',
foo: '',
bar: undefined
});
The new DOM element will look like this:
<div foo=""></div>
Ext.fly()
Ext.dom.Fly
is now a separate class, and just like Ext.dom.Element
, it should not be instantiated by calling the constructor. Always use Ext.fly()
to retrieve a flyweight element instance. The major change in behavior for flyweight Elements is that you can no longer attach event listeners (addListener and removeListener raise errors in development mode). Always use Ext.get()
to retrieve an Element instance if it will be used to attach event listeners. Using Ext.get()
adds the Element to the internal Element cache which allows its listeners to be cleared upon destruction. While adding listeners to flyweight Elements was not previously recommended, it is now prohibited.
Another minor change to the behavior of Ext.fly()
is that it will no longer allow text nodes to be wrapped, but will return null
if a text node is passed. This was done for consistency with the behavior of Ext.get()
.
Element Selection Methods (select, query)
For better performance, we have changed the select()
and query()
methods to use querySelector
or querySelectorAll
, and have removed the Ext.dom.Query
requirement. Developers who require the advanced selectors supported by Ext.dom.Query
can use Ext.dom.Query
directly. You may also restore the old functionality of Ext.dom.Element
query()
and select()
methods, using an override such as the this:
Ext.define('Ext.ElementCompat', {
override: 'Ext.dom.Element',
requires: [ 'Ext.dom.Query' ],
select: function(selector, composite) {
var elements;
if (typeof selector == "string") {
elements = Ext.dom.Query.select(selector, this.dom);
}
else if (selector.length !== undefined) {
elements = selector;
}
return composite ? new Ext.CompositeElement(elements)
: new Ext.CompositeElementLite(elements);
}
}, function(DQ) {
Ext.query = function(selector, root, type, single) {
return DQ.select(selector, root, type, single);
};
});
Element Position Query
To provide better inspection of DOM element position, Ext JS allows querying the Left, Right, Top, and Bottom of an element based on its local position and its absolute position. Previously, Element.getLeft()
would always return a local coordinate. In order to achieve the same behavior, one will need to call Element.getLeft(true)
to force the local coordinate system. This also applies to getRight
, getTop
, and getBottom
.
In Sencha Touch 2.x, the following Ext.dom.Element
methods returned “local” coordinates by default. Local coordinates are relative to their offsetParent
. In Ext JS 6, however, these methods return “global” coordinates (relative to the page) by default:
- getTop()
- getRight()
- getLeft()
- getBottom()
Users may revert to using local coordinates by passing true as the first parameter to any of these methods, for example:
myElement.getTop(true);
Changes to platformConfig
To provide for more control over run-time configuration the platformConfig
directive has been overhauled to now work with Ext.platformTags
. This is an object populated early in the framework load process with various identifiers such as phone, tablet, desktop, ios or android etc..
In Sencha Touch 2.x platformConfig
was specified in the following syntax:
platformConfig: [{
platform: 'phone',
theme: ['Windows'],
itemHeight: 43
},{
theme: ['Cupertino'],
itemHeight: 49
}]
In Ext JS 6, platformConfig
is now an object that uses expressions as keys. Whenever the expression is true, those properties are applied. The expressions are implicitly based on the properties of Ext.platformTags
.
platformConfig: {
'phone && windows': {
itemHeight: 43
},
ios: {
itemHeight: 49
}
}
Note: The theme is not a tag available to platformConfig
. If one wished to make the theme (or other tag) available for platformConfig
usage, it can be simply added using the tags
property in "app.json"
(perhaps in a build profile):
"builds": {
"cupertino": {
"toolkit": "modern",
"theme": "theme-cupertino",
"tags": "cupertino" // added to platformTags for this build
}
}
Alternatively, applications can provide Ext.beforeLoad()
which is given this object and it is also valid to modify it if needed. Perhaps, to add a custom tag.
<script type="text/javascript">
var Ext = Ext || {}; // Ext namespace won't be defined yet...
Ext.beforeLoad = function (tags) {
// ... tags === Ext.platformTags
tags.custom = true;
};
</script>
Theming
iconCls / Pictos
The Pictos icon font is no longer included by default. It is now a separate package you’ll need to require explicitly in "app.json"
or "package.json"
as appropriate:
"requires": [
"font-pictos"
]
Once required, you can use the following syntax for iconCls
configs in order to use icons from the Pictos library:
// pictos-{iconName} is used to set a named icon from the Pictos icon set
iconCls: 'pictos pictos-home'
A similar requirement step and iconCls
syntax will be used if you prefer to use icons from the new “font-awesome” package.
"requires": [
"font-awesome"
]
// fa-{iconName} is used to set a named icon from the Font Awesome icon set
iconCls: 'x-fa fa-home’
Theming Upgrade
Creating custom themes in Touch is very different than how it’s handled in Ext JS. Any custom theme style rules that existed in your Touch Application will need to move into the appropriate folders.
See our Theming Guide for more information about theming Ext JS.
Fashion
We are very excited to introduce our new theme compiler named Fashion. Fashion compiles most Sass code (.scss
files) but is in fact not Sass. It is an extended language with additional features to improve use in tools like Sencha Inspector.
Dynamic Variables
When upgrading to Ext JS 6, the internal use of dynamic variables could impact how these variables are assigned in applications and custom themes. Although not necessary, it is recommended to change variable assignments to use dynamic()
. In most cases, this will mean mechanically replacing !default
(the approach taken in previous releases) with dynamic()
:
// before:
$base-color: green !default;
// after:
$base-color: dynamic(green);
This will make it more obvious if an error is generated based on the more restrictive nature of assignment to dynamic variables.
Compass Extensions
Compass functionality depending on Ruby code will be unavailable since Ruby is no longer being utilized. An equivalent will have to be created using JavaScript. This can be provided in many cases using require()
to implement the missing functionality in JavaScript. The Sass code from Compass, however, is included in Fashion, so not all Compass functionality is impacted. Generally speaking, if you have not used any custom Compass functionality, you will most likely not need to make any changes.
See the Fashion Guide for more information.
Events
Declarative Listeners
Previously, listeners declared on the class body would be merged at a property level with listener declarations on subclasses or instance configs. This could lead to surprising results should options like delay
and buffer
get merged.
Now, listeners declared on the class body will never be merged. Instead, listeners defined on subclasses, or in instance configs will be added to any existing listeners inherited from super classes and/or mixins. This enables listeners to be safely defined in a declarative manner.
In the following example all three listeners will be called:
Ext.define('SuperButton', {
extend: 'Ext.button.Button',
listeners: {
click: function() {
console.log('button clicked (superclass handler)');
}
}
});
Ext.define('SubButton', {
extend: 'SuperButton',
listeners: {
click: function() {
console.log('button clicked (subclass handler)');
}
}
});
Ext.create('SubButton', {
renderTo: Ext.getBody(),
text: 'click me',
listeners: {
click: function() {
console.log('button clicked (instance handler)');
}
}
});
Users who were dependent upon the past behavior of declarative listeners that overrode their parent class’s listeners will need to change their code to override the handler method instead.
Updating “before” Event Listeners
Sencha Touch and Ext JS had different approaches to before
and after
events. In Sencha Touch, you might see code like this:
listeners: {
activeitemchange: 'onBeforeActiveItemChange',
order: 'before'
}
This listener would be called prior to the change of active item and could veto that change by returning false. In Ext JS, the above should be changed to:
listeners: {
beforeactiveitemchange: 'onBeforeActiveItemChange'
}
This would also apply to many cases using onBefore directly:
// Before:
comp.onBefore('activeitemchange', 'onBeforeActiveItemChange', this);
// After:
comp.on('beforeactiveitemchange', 'onBeforeActiveItemChange', this);
The after
event order and onAfter
method, which is also deprecated, are similar but should function in much the same way as in Sencha Touch.
Details
In the core event system with Ext JS 6, the order
option on listeners is deprecated and simply maps to a priority
value to control the order of event listeners. While this preserves the ordering of listeners to an event, it does not have the expected result for before
listeners in all cases.
This is particularly true when listening to events fired using fireAction (the implementation that was behind eventedConfigs). In Sencha Touch, the one event (“activeitemchange” for example) would be fired to all “before” listeners. If none returned false, the action function would be called and then all remaining listeners would receive the event. To handle animations and the like, the event delivery would be suspended and resumed (typically by the action function).
With Ext JS 6, this is split into two events (“beforeactiveitemchange” and “activeitemchange”) and the action function is called between the two events (if no “before” event listeners returned false).
Event listening
Advanced listening features like listening directly on elements or components using wildcard and advanced selectors may not work the same. Application level event handlers using controllers or viewControllers, however, will work the same.
Scrolling
The scrollable
config of Ext.container
now configures an Ext.util.Scroller
instead of an instance of Ext.scroll.View
.
With many touch-enabled devices, special logic is needed to efficiently manage scrolling. To normalize all this device-specific behavior, we’ve added Ext.scroll.Scroller
. An instance of this class is created by the framework when using configs like autoScroll
, overflowX
and overflowY
configs, but it can now be more fully controlled using the new scrollable
config.
This config can now be a config object for the Scroller. To retrieve the Scroller, you call getScrollable()
. This object provides useful APIs like scrollTo
and scrollBy
, so you no longer need to worry about how the scrolling is managed on the current device.
The properties in a scrollable config object are transferred to configs of a Ext.util.Scroller
.
Now you can use the preferable shorthand like so:
scrollable: 'x' // equivalent to 'horizontal'
scrollable: 'y' // equivalent to 'vertical'
Data
The Ext.data
namespace is perhaps the most impacted by the merge of Ext JS and Sencha Touch.
Ext.data.Model
The way to define models has changed to not require a config block, because they are not instance level configurations:
// Old
Ext.define('Order', {
extend: 'Ext.data.Model',
config: {
fields: ['id', {
name: 'date',
type: 'date'
}],
hasMany: 'OrderItem'
}
});
// New
Ext.define('Order', {
extend: 'Ext.data.Model',
fields: ['id', {
name: 'date',
type: 'date'
}],
hasMany: 'OrderItem'
});
The internals of Ext.data.Model
have been heavily optimized to include support for calculated fields, better identity (“id” property) management, and undeclared fields.
This last item takes a bit of unpacking. Basically if the following are true for a field then that field no longer has to be listed in the fields array:
- Needs no conversion beyond deserialization (say from JSON)
- Has no default value
- Does not need to be validated (at the Model level)
Properties / Configs
data: Undeclared model fields will remain intact where they were previously pruned in Touch. This allows Models to only define the fields that need to be processed in some way. The data object passed to the constructor simply becomes the
data
property and defaulting and conversions are applied in place.raw: Because of the changes to the data property, there is no longer a separate raw data property tracked on each record. Should your existing applications rely on this previously reader-generated property, you can approximate the old behavior during the transition with a simple override to copy the data before it is updated:
Ext.define('App.overrides.data.Model', { override: 'Ext.data.Model', constructor: function (data) { this.raw = Ext.apply({}, data); this.callParent(arguments); } });
id / internalId: When a record is created and no “id” is given, one will be generated. This is handled by the Model’s
identifier
config. This is placed asid
on the record (accessed using thegetId
method) as well as in thedata
object as theidProperty
. Historically, the id would often be copied to the internalId. This is no longer the case. TheinternalId
is a separately generated value that is unique across all records and should never be changed. Theid
, however, may be changed.clientIdProperty:
clientIdProperty
is now a config for writer that is used to rename “id” as it is sent to the server for create operations. If now present, the generated “id” will be sent. The server’s response is used to send back the server-generated id as needed. The id sent to the server is read back using the existingclientIdProperty
on Model. When using a Session, the “foreign key” fields of all associated records will be updated, if maintained within the same session.modified:
Ext.data.Model
previously returned an empty object for the modified property if no records had changed. Accessing the Model’smodified
property will now returnundefined
if no changed records have been appended. Changes such as these allow the Data package to remain as slim as possible.useCache: Sencha Touch gave users the ability to cache model instances by defining their models with the
useCache
config. This was replaced byExt.data.Session
to allow for better scope control over the cache. Alternatively, developers can load records via ViewModel and share it in that manner.
Users should now utilize the model’s “modified” methods to ascertain change. These include:
isModified()
getModified()
getChanges()
belongsTo:
belongsTo
can often be simplified using thereference
config on field.hasMany: The typical use of
hasMany
is deprecated in favor ofreference
config on field. See below. Use ofhasMany
to describe child items that do not contain a foreign key is still appropriate.associations: Same as above since this config is just an alternative way of expressing
belongsTo
andhasMany
.association data will not be read via the model constructor, this will need to be parsed by a reader:
var results = MyModel.getProxy().getReader().read(rawData);
validations: validations are supported but deprecated for creating validators associated with a single field. Instead, use the
validators
config object which is keyed by field name.
Methods
constructor: To construct a record, you simply pass the data object. The second argument is the owning
Ext.data.Session
(see below).drop: There is now a
drop
method that marks the record to be removed, but does not save it immediately.
Ext.data.Store
There are several internal changes to stores in Ext JS 6. Many are inherited from Sencha Touch and others are to support chained stores.
Events
The addrecords
, removerecords
and updaterecords
events now become add
, remove
and update
respectively. The add
and remove
events may be fired multiple times for a single operation, an event will be fired for each contiguous block of records.
// This will cause 2 remove events to be fired, one for each block of records
var records = [0, 1, 4, 5, 6, 9, 10, 12].map(function(idx) {
return store.getAt(idx);
});
// Fires 4 remove events:
// 0..1
// 4..6
// 9..10
// 12
store.remove(records);
datachanged event: In some cases, previous Sencha Touch 2 releases did not always fire this event consistently. Ext JS now assures that this event is raised for all manual bulk load methods such as loadData
, add
, or insert
. Note that this event is not raised initially when a store is instantiated with inline data: [ ]
.
Added
beginUpdate / endUpdate: These methods can be called before making multiple changes to a store and after. These translate to new beginupdate
and endupdate
events as these transition an internal update counter from or back to 0. This allows views observing the store to defer expensive operations out to the endupdate
event.
Changed
getById / getByInternalId: In Sencha Touch 2, only getByInternalId
was a map lookup, and since internalId
was not always the same as id, applications needed to call getById
. In Sencha Touch 2, that was a linear search, but both are backed by maps.
destroy / destroyStore: In Sencha Touch 2, the “destroy” method was used to send a remote request to the server to delete records. This conflicts with the common usage of “destroy” across the framework to mean to clean up resources. To bring this in line, the “destroy” method now cleans up a store. To send a delete request to the server, the “erase” method (same as model) should be used. “destroyStore” is deprecated.
Deprecated / Removed:
“buffered” config: The buffered
config is supported for Ext.create and operator new, but is deprecated. It is recommended to create a buffered store using type: 'buffered'
. If you are deriving a store from Ext.data.Store
, the buffered
config is not supported. Instead derive from Ext.data.BufferedStore
. Here’s an example of a grid store config:
store: {
type: 'buffered', // was "buffered: true",
...
}
groupers: Support for multiple grouping levels was never realized in Sencha Touch 2 and groupers was really nothing more than extra sorters. This has been replaced by the grouper
config and the getGroupString
method that was previously configured on the store is now configured on the grouper
. The internal structures are now much closer to being able to support nested groupers and this config will most likely be restored when that functionality is available.
Ext.data.Proxy
Ext.data.Operation
has now been split into four subclasses, one for each type of CRUD operation. These operation classes should be used in favor of Ext.data.operation.Operation
directly.
Proxy
“destroy” / “erase”: Similar to
model
&store
, thedestroy()
method has been corrected to mean clean up any resources. To send a delete request to the server, theerase
method should be used.“doRequest”: Now takes a single argument, an
Ext.data.operation.Operation
. Callbacks should be attached to operation directly.
Proxy CRUD
One could previously pass a callback and scope into proxy CRUD methods. This has been removed. The callback from the proxy would return the operation where now one would use a callback on the operation which returns the results instead.
Writer
- writeAllFields: The default for this config was true and is now false to optimize data transfer. This config is used to tell the Writer to send all fields on an update even if those fields have not changed.
Ext.data.Field
One of the biggest changes to fields is that the various field types are now defined as classes in a small class hierarchy Ext.data.field.*
. Now you can write custom field types and use them in your Models by simply giving them an alias (for example, data.field.foo
) and using that name as the type config on a field (for example, ‘foo’).
depends: You can now declare the field names that a
convert
function uses to calculate its value and this field will automatically be updated whenever any of these fields are set.calculate: This new config allows you to write a simple function that produces the value of a field given the record’s data object. Instead of declaring a
convert
function and thedepends
array, this text of this function is parsed to extract the field dependencies.reference: To make it simple to relate one Model with another, when a field contains the id of another record (a “foreign key”), you can add this config and simply give the name of the Model being referenced. This is enough to populate association data for both this Model and the referenced Model.
validators: This config is typically used when deriving a custom field type, but this is an easy way to list the rules that describe a valid field value.
useNull: This config is now named
allowNull
.
The ability to derive custom field types replaces the Ext.data.Types
static class, which has been deprecated.
Ext.data.Validations
Has been replaced by Ext.data.validator.*
.
Sessions (NEW)
The new Session class will help manage editing of multiple records and their associations. If you are manually saving records and stores and have to work out the proper sequence to save all of your edits, the Session class will likely be very helpful. Check out the API documentation on Ext.data.Session
to determine if you might benefit from coordinated Model management.
Schema (NEW)
Collecting and managing all of your Model definitions and their associations is now handled by the Schema class Ext.data.schema.Schema
. The Schema class knows, for example, when one class declares an association with another and ensures that both classes are “decorated” with appropriate accessor methods - regardless of the order in which those classes are loaded.
ModelManager (DEPRECATED)
The Ext.data.ModelManager
class is deprecated. Its features have been replaced by Ext.data.schema.Schema
.
Associations
The way you declare associations has been streamlined. The old syntax is supported but, in many cases, field’s new “reference” config makes the declaration much simpler. Further, Ext JS now supports “Many-To-Many” associations using the ManyToMany
Model config.
Ext.data.association.* (REPLACED)
The contents of this namespace have been replaced by Schema. Direct use of these classes in applications is rare and the configs that corresponded to these classes (“belongsTo”, etc) are still supported though most deprecated.
Ext.plugin.BufferedList
We have removed Ext.plugin.BufferedList
. Please use infinite: true
on list instead.
mainView
Using mainView
is the preferred way to launch your application. While you can still utilize the launch method, it’s more tool friendly to use mainView
.
The mainView
config can, however, conflict with a “Main” view listed in the views
array:
views: [
'Main' // generated getter conflicts with mainView config getter
]
To resolve this conflict, you can:
- Switch the Main view to be created via the
mainView
config. - Rename the Main view.
- Remove the “Main” entry in the
views
array (and check calls togetMainView
).
Viewport
Previously in Touch the Viewport was available at the time of onReady
. ExtJS 6+ now has an event that fires when the Viewport is ready.
Ext.on('viewportready', cb);
Using the viewportready
event will allow users to access the viewport as soon as it is created from anywhere in there application.
Removed Ext.DateExtras
The Ext.DateExtras
singleton class has been removed. Most of the methods found in Ext.DateExtras
can be found in Ext.Date
instead.
Ext.data.plugin.Buffered has been removed
Use Ext.data.BufferedStore
. At present, Ext.data.BufferedStore
may not support Create, Write and Delete operations. However, we are in process of making modern components accept BufferedStores.
Legacy Package
We have created a legacy package that contains no longer supported code (like Ext.device.*
, see below). The intent of the legacy package is to give users a chance to update their code before the code they may have used is completely removed.
Ext.device.* API have been moved to legacy package
We have removed the Sencha Touch device API’s from the modern toolkit, but they can still be utilized by requiring the legacy package. While Ext.device.*
can still be used, we recommend using native HTML5 API’s or, for native packaged applications, Cordova or PhoneGap APIs are the preferred method of providing native device support.
Ext.data.proxy.Sql has been removed
Ext.data.proxy.Sql
was based on webSQL, which is no longer being developed. Additionally, it’s only supported in webkit browsers.
Charts Package
Ext.draw.Component
Ext.draw.Component
has changed to Ext.draw.Container
.
Instance IDs
As part of our performance optimization efforts in Ext JS 6, we have removed the overhead for handling identifiers with invalid characters from certain core areas. To help catch such ids before they fail, we have added checks in key places such as Ext.get()
and the Ext.Component
constructor. These checks use Ext.validIdRe
, which is defined as:
validIdRe: /^[a-z_][a-z0-9\-_]*$/i
In a nutshell, create ids that adhere to the above regex in order to future-proof your application.
Ext.ComponentManager
Ext.ComponentManager
is seldom used directly by applications, but its internals have been streamlined and it no longer provides a HashMap of components. Instead look at the methods this class provides to access the registered components.
Ext.Container
Ext.Container
API has been changed to be more consistent with Ext.container.Container
API in Classic toolkit. The changes include:
- When calling
add
method with multiple items to add, the return value will be an array ofExt.Component
instances that were added to the Container. remove
method accepts three types of item selectors: anExt.Component
instance,itemId
of a child Component, or numeric index of the child Component in theitems
collection.remove
method will return the removed item instead ofthis
.removeAll
method will return an array of removed items instead ofthis
.removeAt
method will return the removed Component instead ofthis
.removeInnerAt
method will return the removed Component instead ofthis
.
Ext.mixin.Selectable (affects Ext.dataview.DataView, Ext.List, Ext.grid.Grid & subclasses)
The getSelection
method now returns a single record, the most recently selected one. This can be used for databinding:
{
xtype: 'formpanel',
items: [{
xtype: 'textfield',
bind: '{theList.selection.name}'
}]
}
Use getSelections
to return an Ext.data.Model[]
that has all selected records.
Forms
Ext.field.Text (and subclasses)
The change
event now fires immediately as the input changes, instead of when the field blurs. To have a delay to capture multiple change events in succession, use a buffer on the listener:
listeners: {
// Each time the change occurs, it will wait 500ms. If no other change has happened in
// that period, the event will fire. Otherwise, if a change does happened, the timer will
// be reset and the process will repeat
buffer: 500,
change: function() {}
}
Ext.field.Checkbox
The check
and uncheck
events no longer pass the event object as it was only available under some circumstances, the event was fired whether the change occurred via the UI or not.
Ext.field.DatePicker, Ext.field.Select
This class no longer extends Ext.field.Select
, the picker related functionality has been abstracted into Ext.field.Picker
, both of these classes now extend Ext.field.Picker
.
Ext.field.SingleSlider
This class has been introduced to assist with data binding. It is very similar to the superclass, Ext.field.Slider
, however the getValue
method and value
binding always return a Number
, not a Number[]
.
Ext.field.Slider
The change
event is now consistent with other form fields, the the signature is now:
change: function(field, newValue, oldValue) {}
What was previously the change
event is now named dragchange
.
A new liveUpdate
config was added to determine when the change
event fires, either real time as the slider is modified, or when the drag is complete.
Ext.field.Toggle
The type of value
for this field is now a Boolean. It will still accept numeric values.
Misc
Ext.util.Draggable
To veto a drag, listen to the beforedragstart
event and return false. In previous versions this would be done in the dragstart
event.
Conclusion
As you can see, there are many new additions for users moving from Touch to the Modern toolkit. As always, if you have questions regarding guide content, be sure to ask on the community forums or by submitting a Support ticket through the Support Portal (Sencha Support customer access only).