Latest Ext JS 7.8 is now available. Learn more

Declarative Listeners in Ext JS 5 Explained

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

8 Must-Know Tips for Choosing the Right Web Application Framework for Your Project

Starting web application development on a project can feel like a very difficult task. The abundance of frameworks adds to the confusion. It leaves developers…

Web Application Development | Top 10 Frameworks in 2024

If you are a developer, you must know the role of frameworks in creating amazing applications. Web application development frameworks come with pre-built tools to…

Understanding the Difference: When to Use Ext JS Classic vs. Modern Toolkit

Ext JS is a JavaScript framework for building powerful web and mobile applications. The framework features over 140+ high-performance, fully tested, and customizable UI widgets/components.…

Ext JS 7.8 Has Arrived!

The Sencha team is pleased to announce the latest Ext JS version 7.8 release. Following the 7.7 release, which included numerous quality enhancements in Ext…

How to Work with Ext JS Models and Stores: Tutorial on Managing Data and State

Ext JS is a popular JavaScript framework for creating robust enterprise-grade web and mobile applications. The framework offers a rich set of high-performance and fully-tested…

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 not the case anymore. Modern software development requires apps to…

View More