Historical Background
Most likely many of you who will read this article do not remember times of Fortran language and computers that were fed with tons of punch cards to have some some job done.
The main purpose of computers at that time was to compute something really; that is not true anymore because computers are used for getting computational result very rarely at schools or scientific institutions nowadays.
How did it work at that time? If you wanted a computer to run a program you went to a shelf with your punched cards, you found the drawer with the stack of them, fed them through card reader and the computer started your program.
First task was to ask for user inputs and once you filled them in the program computed the result, printed it and ended. Easy, straightforward, “single thread” job.
Events Introduced
With the invent of GUI and Mouse this concept of load-run-end just couldn’t work anymore as we needed some infinite loop that would wait for user actions (mouse movement and clicks) and that would process them to execute the required actions.
I has became clear very soon that putting the code that processes these action directly in that loop is the route to nowhere so the Event driven programming was born.
Event Definition
Event is a message, a function call, generated by one (part of) program, the event source, that notifies another (part of) program, the event listener, that something happened. Events are generated as responses to user actions or to state changes of the event source.
The event source is independent of event listeners and it generates events also if nobody listens or even if there is no listener defined. The viewpoint of our infinite loop would be: “I’m informing everybody that user moved the mouse to position [x,y] and I do not care who listens, if anybody.”
The viewpoint of the listener would be: “Let me know when user moves the mouse, I need to do something with it.”
Events in Ext
There are two main “sorts” of events in Ext: DOM events and JavaScript, or software, events.
DOM Events
Browsers that display (X)HTML pages already have our “infinite loop” that watches user actions and fires events if these actions are occurring on DOM elements. Before Ext we were used to install event listeners on DOM elements this way:
Ext.Element wraps DOM elements together with their events so now we install the same event handlers this way:
Ext.get('mydiv').on('click', function() {alert('You clicked me');});
It can be said that DOM events are “passed-through” from DOM through Ext.Element to listeners.
JavaScript Events
Now, DOM elements are not only possible event sources; it is quite easy to implement event source logic and event listener installation to any JavaScript object. But, what could it be good for?
Imagine that you have a complex component such as grid. If you had only DOM events, the handling of user actions such as column move would be extremely difficult. You would need to listen to DOM elements, process mouse clicks, moves, calculate from where to where the column has been moved, etc. If would be much easier if grid component would do all this dirty work for you and, after everything has be done, just informed you: “User moved column 3 to position 1.”
That is exactly what grid does: it fires JavaScript events that inform potential listeners what has happened to it. The same is true for another Ext components. Form validation events, Panel resize events, Tree expand/collapse events can serve as examples, to name a few.
How do I listen to events?
If you have an object of Ext class, for example Panel, and you need to do some action when panel resizes you would install a listener to implement your action:
// create panel var myPanel = Ext.create('Ext.panel.Panel', {...}); // install resize event listener myPanel.on('resize', function(panel, w, h) { alert('Panel resized to ' + w + 'x' + h); });
From this point on, whenever the panel myPanel
is resized your function is called so you can do your actions.
How do I create event source?
Events related functionality is implemented in Ext.util.Observable class so if you want your extension to be an event source just extend Observable. Also, if you extend a class that is already descendant of Observable (Panel, Grid, Form, Tree, etc), your extension is automatically the event source.
Events fired by your extension are events fired by parent class(es).
Custom Events
It happens very often that you need add new events, for example you create Employee class and Organization Chart class and you implement drag&drop assignment/dismissal of employee to/from a position. I would come handy to fire event assigned and dismissed, wouldn’t it?
We could listen to these events and the listeners could send e-mails to the employee informing him that he has been assigned to a position or dismissed from it.
We do it this way:
OrgChart = Ext.extend(Ext.Panel, { initComponent:function() { // call parent init component OrgChart.superclass.initComponent.apply(this, arguments); // add custom events this.addEvents('assigned', 'dismissed'); } ,assign:function(employee, position) { // do whatever is necessary to assign the employee to position // fire assigned event this.fireEvent('assigned', this, employee, position); } ,dismiss:function(empoyee, position) { // do whatever is necessary to dismiss employee from position // fire dismissed event this.fireEvent('dismissed', this, employee, position); } });
In the initComponent
function we inform Observable class that we are going to fire our new events so it can do all necessary setup.
Note: We do not extend Observable directly here but Panel, what we extend, does. Panel’s inheritance chain is: Observable -> Component -> BoxComponent -> Container -> Panel.
And in assign
and dismiss
functions we fire our events after all assign/dismiss job has been done with signature (arguments) of our choice.
When we fireEvent
, Observable looks if there are some listeners to this event and calls all listeners with arguments we supplied in fireEvent
call. If there is no listener it just does nothing.
Summary
- event is a message sent (fired) by an event source to inform listeners that something happened
- event source is an object that can fire events
- event listener is a function that is called when event source fires an event
- to listen to events we use
on
function to install an event listener - to create an event source we extend
Observable
class,addEvents
andfireEvent
Enjoy firing your events and listening to them!
- Ext, Angular, React, and Vue - 27. June 2019
- The Site Resurgence - 11. February 2018
- Configuring ViewModel Hierarchy - 19. June 2015
38 Responses
Thanks
one question please:
when we fire event “dismissed” for example that will call the “dismissed” function which also fire the even again! that will lead to execute code inside “dismissed” function forever ?
This is extremely helpful, thank you.
@all, sorry I won’t answer here questions of “How do I …” nature. There is fantasic forum for this at ext home page. http://www.sencha.com/forum
No, no. I’ve been around FORTRAN in 80-ties.
Hi Saki,
I thought That I was the only one still actively building applications that remembered the Fortran days that you describe (NYU 1970 for me). Did your father tell you bedtime stories? 🙂
how do you extend a class and add listener for an event within that ? for example, I would want to control the behaviour of rowdblclick in an extended gridpanel. I want it to be inside of the extended class.
is extending the only way to register a new event?
Can I not directly use addEvents() on a FormPanel?
Thanx in advance.
Hi Saki,
Im using cloneNode method of dom , and cloning a panel , but once i create a clone all the listeners on that panel disappeared. Please suggest me any idea.
–Payal
The best place to ask questions like this is ExtJS forum.
Hi Saki,
I learned a lot about custom events from your article but having time in real time implementation. So If I understood your events surrectly, then you are overriding obserable class of a panel. Now I couldn’t figure out that if I already have a gridPanel and want to implement this custom event then how can I do that. I have Grid declared like this.
grid = new Ext.grid.GridPanel({
store: new Ext.data.Store({
reader: wnode.reader,
id: 0,
data: wnode.data,//SAMPLE GRID
})
Now I want to attach a OnRowOver custom event on that. so how can I do that.. in your case you have extend something like this.
OrgChart = Ext.extend(Ext.Panel, {
initComponent:function() {
// call parent init component OrgChart.superclass.initComponent.apply(this, arguments);
// add custom events
this.addEvents(‘assigned’, ‘dismissed’);
}
I would appreciate any comment. I noticed that there is no OnRowOver attached to this. Please let me know any suggestiosn.
Thanks
Anshu
Hi Renwill,
the best would be to ask the question on the forum.
You can PM me the link if you want.
I am a novice in JavaScript/extjs. How would your example look if I want to avoid memory leakage in IE? I found the following link but don’t quite understand.
http://www.jasonclawson.com/2008/05/17/extjs-performance-event-listeners/
ExtJS Performance – Event Listener Cleanup
Yves,
briefly, yes it looks it can work. Nevertheless, post please your question to Ext forum (you can PM me the link to that post) and I (or maybe also somebody else) will answer you in more details.
Cheers,
Saki
Hi,
We’re having a hard time understanding the nuances in Ext’s event system. We read your post a couple of times but still.
Here’s what our problem is. We have an Ext record from a grid which we serialize to JSON. We want to be able to shove that JSON out to another application. That other application is a JS app, but not an Ext one.
The other application will typically call the Ext application, so we have access to it via window.opener at least. We were thinking of defining a specific event type in the Ext app and raise it upon a click in a button (in the Ext app). That button click would also send the JSON as a parameter, so we were thinking of building a hidden control in the other app.
That control would be activated by the button click on the Ext side and we would define a handler on the click event of that control on the other application side which would take in the JSON string passed as a parameter and do something useful with it. In fact we want the other application to position itself in another object (e.g. an edit form) as a function of parameters stored in a JSON string. Is that something workable ?
TIA,
Yves Moisan
Wait for Ext 3. It implements event bubbling.