Sequence and Intercept are a pair of related methods built into Ext JS that we can use
to add functionality or add fixes to the library without having to
override or create a new component. Why is this important? We will take
a look at our options to get an idea of the restrictions imposed by
each of them, but first I want to frame this all with a scenario.
Patterns – Using Ext JS Sequence and Intercept
Sequence and Intercept are a pair of related methods built into Ext JS that we can use
to add functionality or add fixes to the library without having to
override or create a new component. Why is this important? We will take
a look at our options to get an idea of the restrictions imposed by
each of them, but first I want to frame this all with a scenario.
Scenario (our use case)
Our
goal here is to create a 'required' indicator on all form fields by
setting a required flag on the configuration object of each component -
in our case, form fields. The code base (the web app) is already in
place, so this is a web application that has been completed and is in
use.
We have a few options available to make this happen:
- Override
- Extend
- Intercept/Sequence
Lets take a look at the benefits and problems imposed by these methods.
Override
Of course one way to get what we want is to override a particular
method in the component were using. If were lucky, there is a stub
function in place that we can use, but more often than not, this is not
the case. What were left with is having to copy code from the library
source files and modify it to fit our needs - not the optimal solution.
This means that each time the Ext JS codebase is updated, we need to
check the changes against our overridden copy. This is a maintenance
nightmare, though there are cases where this is the optimal solution.
Extend (new Component)
The better of our two options is the Extend method. This way creates
a copy of the component that we can modify to fit our needs. Not a bad
solution all and all. The two problems here are that any components
that inherit from our extended component will not get our new
functionality, and we now have a copy of the component with a new name,
so each place we use that component needs to use our updated component
name, ie: 'mysupertextfield' instead of 'textfield'. Again, not a big
deal, but if I already have a complete web app, and im adding a bit of
functionality to a common component, I don't want to have to run a
find/replace on the entirety of my code.
Meet intercept/sequence
My personal favorite in this situation is to add our functionality
either before or after an existing method. The intercept method of Ext
JS takes whatever function you provide and executes it right before
whatever method in the component you specify. The function we define is
also executed in the same scope as the method were intercepting.
- Ext.intercept(Ext.form.Field.prototype, 'initComponent', function() {
- var fl = this.fieldLabel, ab = this.allowBlank;
- if (ab === false && fl) {
- this.fieldLabel = '<span style="color:red;">*</span> '+fl;
- } else if (ab === true && fl) {
- this.fieldLabel = ' '+fl;
- }
- });
Ext.intercept(Ext.form.Field.prototype, 'initComponent', function() {
var fl = this.fieldLabel, ab = this.allowBlank;
if (ab === false && fl) {
this.fieldLabel = '<span style="color:red;">*</span> '+fl;
} else if (ab === true && fl) {
this.fieldLabel = ' '+fl;
}
});
With this override, we can use the existing allowBlank flag to trigger the required indicator
- ...
- {
- fieldLabel: 'Last Name',
- allowBlank: false,
- name: 'last'
- },{
- fieldLabel: 'Company',
- allowBlank: true,
- name: 'company'
- }
- ...
...
{
fieldLabel: 'Last Name',
allowBlank: false,
name: 'last'
},{
fieldLabel: 'Company',
allowBlank: true,
name: 'company'
}
...
In this case, intercept seems to be the perfect fit, allowing us to
add a visual required indicator to each component that is extended from
the Field base class. The one downside I see here is that this code is
executed every single time a field is created, so be sure to make it
lean.
We could also use Sequence to achieve this, which uses the same
syntax and concept as Intercept, but executes after the method we
define has executed instead of before. The order of execution is like
this:
- Intercept
- Method (ie: initComponent)
- Sequence
|