JS Days 2025 Replays are now live! Watch all sessions on-demand Watch Now

Declarative Listeners in Ext JS 5 Explained

September 10, 2014 6285 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.

Recommended Articles

Why Rapid Ext JS Is Ideal for Developers Who Need Speed, Scalability, and Rapid Application Development

Rapid Ext JS, which is an Extended JavaScript framework, speeds up app development using low-code tools. It makes building apps that can grow with your…

Guide to Estimating ROI When Switching From DIY Libraries to Full Software Development Platforms Like Ext JS

Teams started with Do It Yourself, or DIY, JavaScript tools like jQuery and Bootstrap. But those fall apart as projects scale. Scattered code, user interface…

Top Frameworks Developers Are Using for Custom Software Development in 2025

We’re seeing it more every year; teams aren’t settling for plug-and-play tools anymore. In healthcare, finance, logistics, and other data-heavy industries, there’s a clear shift.…

Meet Sencha AI Coding Companion: Your AI-Powered Assistant for Faster Ext JS Development

Building modern web applications should be exciting. But too often, developers find themselves buried in documentation, endlessly Googling framework quirks, or stuck solving the same…

Ext JS 7.9 & Rapid Ext JS V1.1 Have Arrived

The Sencha team is excited to announce the latest Ext JS version 7.9 and Rapid Ext JS 1.1 release – designed to accelerate development, enhance…

Top 10 JS Grid Customization Tips for a Better UI Experience

Grids are pretty much everywhere in web apps. Working with financial sheets, product details, or users? Then you’ve probably used a JavaScript grid. It makes…

View More

Trusted by Top Developers: Learn how to enhance your development journey — for free

Get the latest newsletter keeping thousands of developers in the loop.

Loved by developers at
JSDays Replay