Introducing React ReExt – Sencha Ext JS Components in React! LEARN MORE

Declarative Listeners in Ext JS 5 Explained

September 10, 2014 136 Views

Declarative Listeners in Ext JS 5

In the article, Using ViewControllers in Ext JS 5, we touched briefly on a feature improved in Ext JS 5. That is the “Declarative Event Listeners.” In this piece, we’ll dive in deeper and explore how you can use declarative listeners to;

  • Simplify your application’s Views, and 
  • Reduce boilerplate code in your custom Components.

Note: This article assumes you are using the Ext JS 5.0.1 version or higher.

What Are Declarative Listeners?

When we say “declarative listeners,” we refer to listeners registered on the body of a class or the configuration object of an instance using the listeners’ config. This feature is not new to the Ext JS network. In Ext JS 4, you could declare listeners on a class, but only if the handler function or scope had already been defined. For example:

Ext.define('MyApp.view.User', {
extend: 'Ext.panel.Panel',

listeners: {
// function must inline or previously defined:
collapse: function() {
// respond to panel collapse here
}
},

// This method cannot be declared as the collapse handler:
onCollapse: function() {
}
});

Declarative listeners were limited in Ext JS 4 because the requested handler function was not always accessible at class definition time. Developers typically added listeners by overriding initComponent and using the on method like this:

Ext.define('MyApp.view.User', {
extend: 'Ext.panel.Panel',

initComponent: function() {
this.callParent();

this.on({
collapse: this.onCollapse,
scope: this
});
},

onCollapse: function() {
console.log(this); // the panel instance
}
});

What Is The Scope Resolution Solution?

This was our solution. We improved the listener’s config in Ext JS 5 by allowing event handlers to be specified as strings that correspond to method names. The framework resolves the method names to actual function references at run time (any time an event is fired). We call this process the “Listener Sope Resolution.”

In Ext JS 4, you could only resolve string handlers if an explicit “scope” was given. In Ext JS 5, we added special rules for default scope resolution when a “string” listener is declared without an explicit scope.

Scope resolution has two possible outcomes:

  • A component or 
  • A ViewController.

Whichever the result, the search begins with the component. It could be that the component or its ViewController is the scope. And if not, the framework will “climb” the component hierarchy until it finds a suitable component or ViewController. Here’s how it works;

Part 1: Resolving Scope to Components

The first way that the framework resolves scope is to look for a component with the defaultListenerScope config set to true. For listeners declared on the class, the search begins with the component itself. Look at this;

Ext.define('MyApp.view.user.User', {
extend: 'Ext.panel.Panel',
xtype: 'user',
defaultListenerScope: true,

listeners: {
save: 'onUserSave'
},

onUserSave: function() {
console.log('user saved');
}
});

This listener is then declared on the “class body” of the User view. This means that the framework will check the User view itself for defaultListenerScope before ascending the hierarchy. In this case, because the User view has defaultListenerScope set to true, the scope for this listener will resolve to the User view.

For listeners declared on an instance config, the component itself is skipped, and the framework searches upward, starting with the parent container. Like shown in the example below:

Ext.define('MyApp.view.main.Main', {
extend: 'Ext.container.Container',
defaultListenerScope: true,

items: [{
xtype: 'user',
listeners: {
remove: 'onUserRemove'
}
}],

onUserRemove: function() {
console.log('user removed');
}
});

This type of listener is declared on the “instance config” for the User view. Meaning that the framework will skip the User view (even though it was declared with defaultListenerScope:true) and resolve upward to the Main view.

Part 2: Resolving Scope to ViewControllers

In Ext JS 5, we introduced a new type of Controller called, Ext.app.ViewController. We covered ViewControllers in detail in Using ViewControllers in Ext JS 5, so we’ll focus only on event listeners as they relate to ViewControllers in this discussion.

In contrast to Ext.app.Controller, which can manage many views; each ViewController instance is bound to a single View instance. Because View and ViewController have a one-to-one relationship, the ViewController can serve as the default scope for listeners declared on its View or View’s items.

The same rules apply to ViewControllers as to defaultListenerScope. Class-level listeners always look for a ViewController on the component itself before searching upward in the component hierarchy. For Instance;

Ext.define('MyApp.view.user.User', {
extend: 'Ext.panel.Panel',
controller: 'user',
xtype: 'user',

listeners: {
save: 'onUserSave'
}
});

Ext.define('MyApp.view.user.UserController', {
extend: 'Ext.app.ViewController',
alias: 'controller.user',

onUserSave: function() {
console.log('user saved');
}
});

The above listener is declared on the “class body” of the User view. Because the User view has its own controller, the framework will resolve scope to the UserController. If the User view did not have its own controller, then the scope would resolve upwards in the hierarchy.

On the other hand, instance-level listeners skip the component and resolve to a ViewController upward in the hierarchy, starting with the parent Container. For example:

Ext.define('MyApp.view.main.Main', {
extend: 'Ext.container.Container',
controller: 'main',

items: [{
xtype: 'user',
listeners: {
remove: 'onUserRemove'
}
}]
});

Ext.define('MyApp.view.main.MainController', {
extend: 'Ext.app.ViewController',
alias: 'controller.main',

onUserRemove: function() {
console.log('user removed');
}
});

How Is Listener Config Merged?

In Ext JS 4, listeners indicated on a base class could be completely overwritten by a listeners’ config, declared on a subclass or instance. In Ext JS 5, we improved on the listeners API by properly merging declared listeners between base classes, subclasses, and instances. To see this in action, let’s look at a simple example:

Ext.define('BaseClass', {
extend: 'Ext.Component',
listeners: {
foo: function() {
console.log('foo fired');
}
}
});

Ext.define('SubClass', {
extend: 'BaseClass',
listeners: {
bar: function() {
console.log('bar fired');
}
}
});

var instance = new SubClass({
listeners: {
baz: function() {
console.log('baz fired');
}
}
});

instance.fireEvent('foo');
instance.fireEvent('bar');
instance.fireEvent('baz');

In Ext JS 4, the above example would output “baz,” but in Ext JS 5, the listeners’ configs are merged correctly, and the output is “foo bar baz.” This allows classes to declare only the listeners they need without concern for what listeners their superclass might already have.

How Can You Get Started?

Looking for how to get started? Click here to download the latest version of Ext JS today; https://www.sencha.com/products/extjs/evaluate/

Pro tip: When you combine ViewControllers for handling application logic with ViewModels for two-way data binding, you should have a much-improved application development experience. Give it a try and let us know what you think.

Show
Start building with Ext JS today

Build 10x web apps faster with 140+ pre-build components and tools.

Latest Content
Discover the Top 07 Architecture Patterns used in Modern Enterprise Software Development
Discover the Top 07 Architecture Patterns used in Modern Enterprise Software Development

Developing software without an architecture pattern may have been an option back then. However, that’s…

JavaScript Design Patterns: A Hands-On Guide with Real-world Examples
JavaScript Design Patterns: A Hands-On Guide with Real-world Examples

As a web developer, you know how popular JavaScript is in the web app development…

Virtual JS Days 2024のハイライト
Virtual JS Days 2024のハイライト

2024年2月20日~22日、第3回目となる「Virtual JavaScript Days」が開催されました。JavaScript の幅広いトピックを採り上げた数多くのセッションを実施。その内容は、Senchaの最新製品、ReExt、Rapid Ext JSまで多岐にわたり、JavaScriptの最新のサンプルも含まれます。 このカンファレンスでは多くのトピックをカバーしています。Senchaでセールスエンジニアを務めるMarc Gusmano氏は、注目すべきセッションを主催しました。Marc は Sencha の最新製品「ReExt」について、詳細なプレゼンテーションを実施。その機能とメリットを、参加者に理解してもらうべく詳細に説明しました。 カンファレンスは、Senchaのジェネラルマネージャを務めるStephen Strake氏によるキーノートでスタートしました。キーノートでは、会社の将来のビジョンについての洞察を共有しています。世界中から JavaScript 開発者、エンジニア、愛好家が集まるとてもエキサイティングなイベントとなりました。これは、JavaScript…

See More