Sie sind auf Seite 1von 8

Using Ext Loader for Your Application

June 27, 2011 | Jay Garcia


Brand new to Ext JS 4.0 is a class Loader system that makes use of the new depen
dency system. These two powerful new features allow you to create extensive appl
ications that allow the browser to download digest code as necessary.
Today, well be looking at creating a small application that makes use of this new
class Loader system, exercising the dependency management system. Along the way
, well discuss various configuration options for the Ext Loader system.
Learn the latest about Ext JS and HTML5/JavaScript for three intensive days with
60+ sessions, 3+ parties and more at SenchaCon 2013. Register today!
Before we begin, we will fast forward into the future and peek at the results. D
oing so will allow us to identify classes that well need to extend.
001
Our simple app will contain two-way binding to a grid Panel and form Panels, res
pectively called UserGridPanel and UserFormPanel. The UserGridPanel will require
the creation of a Model and a Store to support its operations. The UserGridPane
l and UserFormPanel will be rendered in and managed by an extension to the Ext J
S Window class known as UserEditorWindow. All of these classes will be under a n
amespace called MyApp.
Before we can begin with code, well have to layout the directory structure. Heres
what the folder, organized by namespace, looks like.
002
As you can see with the illustration above, we have MyApp split according to nam
espace groupings or packages. In the end, our entire application will have an inte
r-dependency model that will function like the following illustration.
Even though were organizing our code to mimic the MVC pattern from Ext JS 4, we w
ill not be using it for this example.
003
Well begin by filling out the contents of the index.html file, which sits at the
root of our application and includes all that well need to bootstrap our applicat
ion.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/s
trict.dtd">
<html>
<head>
<title>Ext 4 Loader</title>
<link rel="stylesheet" type="text/css" href="js/ext-4.0.1/resources/css/ext
-all.css" />
<script type="text/javascript" src="js/ext-4.0.1/ext-debug.js"></script>
<script type="text/javascript" src="js/MyApp/app.js"></script>
</head>
<body>
</body>
</html>
The index.html file contains the necessary link tag for the CSS file for Ext JS
4. This youve seen many times, but the inclusion of the ext-debug.js javascript f
ile is something that might raise an eyebrow, as youre probably used to including

ext-all-debug.js for development and ext-all.js for production.


There are a few choices that Ext JS gives you out of the box, each with their ow
n distinct advantages or disadvantages.
Here is a rundown of each of the files.
ext-all-debug-w-comments.js
Debug version of the entire framework, with comments. This is the largest file o
f the bunch and requires the most processing to display in browsers.
ext-all-debug.js
Same as above, but without the comments. Still very large, but very good for deb
ugging in most cases.
ext-all.js
The entire framework concatenated and minified. Debugging is impossible with thi
s file, so it should be used for production systems only.
ext-debug.js
This file contains the Ext JS foundation and whitespace. With this file, you can
remote load all of Ext JS as needed, and it provides the best debugging experie
nce. The tradeoff is that its the slowest.
ext.js
The minified version of ext-debug.js.
Our index.html file made use of ext-debug.js, which is the bare minimum to get d
ynamic loading working. Later on, well show you how you can use ext-all versions
of the framework, allowing you to get the best of both worlds..
Since the UserGridPanel class requires a Model and data Store, well have to devel
op those supporting classes first. Well begin by creating the Model and Store.
Ext.define(MyApp.models.UserModel, {
extend : Ext.data.Model,
fields : [
firstName,
lastName,
dob,
userName
]
});
The above example contains code to extend Ext.data.Model, creating our UserModel
class. By virtue of extending the data.Model class, Ext JS will dynamically loa
d it for us and then create the UserModel class after it and the dependencies fo
r data.Model have loaded.
Next, well create the UserStore class, an extension to Ext.data.Store.
Ext.define(MyApp.stores.UserStore, {
extend
: Ext.data.Store,
singleton : true,
requires : [MyApp.models.UserModel],
model
: MyApp.models.UserModel,
constructor : function() {
this.callParent(arguments);
this.loadData([
{
firstName : Louis,
lastName : Dobbs,
dob
: 12/21/34,
userName : ldobbs
},
{

firstName
lastName
dob
userName

:
:
:
:

Sam,
Hart,
03/23/54,
shart

firstName
lastName
dob
userName

:
:
:
:

Nancy,
Garcia,
01/18/24,
ngarcia

},
{

}
]);

}
});
When creating our singleton UserStore class, we add a new requires key to the Us
erStore prototype. The requires key is a list that instructs Ext JS to fetch any
required classes before our class is instantiated. In this case, we list our Us
erModel class as a required class.
By virtue of our UserModel class being defined in our stores model property, Ext
JS will load it automatically. It is my opinion that listing the class in the re
quires key allows your code to be self-documenting, reminding you that the UserM
odel class is required.
OK. We have our foundation classes created for the views.UserGridPanel, which me
ans we can move on and create the UserGridPanel itself.
Ext.define(MyApp.views.UsersGridPanel, {
extend : Ext.grid.Panel,
alias
: widget.UsersGridPanel,
requires : [MyApp.stores.UserStore],
initComponent : function() {
this.store = MyApp.stores.UserStore;
this.columns = this.buildColumns();
this.callParent();
},
buildColumns : function() {
return [
{
header
: First Name,
dataIndex : firstName,
width
: 70
},
{
header
: Last Name,
dataIndex : lastName,
width
: 70
},
{
header
: DOB,
dataIndex : dob,
width
: 70
},
{
header
: Login,
dataIndex : userName,
width
: 70
}
];
}

});
When looking at the above code, keep a keen eye on the requires key. Notice how
we added the UserStore as a required class. We just configured a direct dependen
cy relationship between our grid Panel extension and our own data Store extensio
n.
Next, well create the form Panel extension.
Ext.define(MyApp.views.UserFormPanel, {
extend
: Ext.form.Panel,
alias
: widget.UserFormPanel,
bodyStyle : padding: 10px; background-color: #DCE5F0;
+ border-left: none;,
defaultType : textfield,
defaults
: {
anchor
: -10,
labelWidth : 70
},
initComponent : function() {
this.items = this.buildItems();
this.callParent();
},
buildItems : function() {
return [
{
fieldLabel : First Name,
name
: firstName
},
{
fieldLabel : Last Name,
name
: lastName
},
{
fieldLabel : DOB,
name
: dob
},
{
fieldLabel : User Name,
name
: userName
}
];
}
});
Because our UserForm class does not technically require any of the classes weve d
eveloped thus far, we dont need to add a requires directive.
Were almost done. We need to create the UserEditorWindow class and then apps.js,
which will launch our application. The code for the UserEditorWindow class is be
low. The class is pretty lengthy because it contains the code for the grid to fo
rm panel binding, so please bear with me on this.
Ext.define(MyApp.views.UserEditorWindow, {
extend : Ext.Window,
requires : [MyApp.views.UsersGridPanel,MyApp.views.UserFormPanel],
height : 200,
width : 550,
border : false,
layout : {
type : hbox,
align : stretch

},
initComponent : function() {
this.items = this.buildItems();
this.buttons = this.buildButtons();
this.callParent();
this.on(afterrender, this.onAfterRenderLoadForm, this);
},
buildItems : function() {
return [
{
xtype
: UsersGridPanel,
width
: 280,
itemId
: userGrid,
listeners : {
scope
: this,
itemclick : this.onGridItemClick
}
},
{
xtype : UserFormPanel,
itemId : userForm,
flex : 1
}
];
},
buildButtons : function() {
return [
{
text
: Save,
scope : this,
handler : this.onSaveBtn
},
{
text
: New,
scope : this,
handler : this.onNewBtn
}
];
},
onGridItemClick : function(view, record) {
var formPanel = this.getComponent(userForm);
formPanel.loadRecord(record)
},
onSaveBtn : function() {
var gridPanel = this.getComponent(userGrid),
gridStore = gridPanel.getStore(),
formPanel = this.getComponent(userForm),
basicForm = formPanel.getForm(),
currentRec = basicForm.getRecord(),
formData = basicForm.getValues(),
storeIndex = gridStore.indexOf(currentRec),
key;
//loop through the record and set values
currentRec.beginEdit();
for (key in formData) {
currentRec.set(key, formData[key]);
}
currentRec.endEdit();
currentRec.commit();
// Add and select

if (storeIndex == -1) {
gridStore.add(currentRec);
gridPanel.getSelectionModel().select(currentRec)
}
},
onNewBtn : function() {
var gridPanel = this.getComponent(userGrid),
formPanel = this.getComponent(userForm),
newModel = Ext.ModelManager.create({},
MyApp.models.UserModel);
gridPanel.getSelectionModel().clearSelections();
formPanel.getForm().loadRecord(newModel)
},
onAfterRenderLoadForm : function() {
this.onNewBtn();
}
});
The code for our UserEditorWindow contains a lot of stuff to manage the full bin
ding lifecycle of the UserGridPanel and UserFormPanel classes. In order to instr
uct Ext JS to load the two classes we created earlier, we have to list them in t
he requires list.
Were now ready to tie this all together in the app.js file. To maximize our learn
ing, well be making three passes at this. Well begin with the simplest configurati
on first, and add more as we progress.
Ext.Loader.setPath(MyApp, js/MyApp);
Ext.onReady(function() {
Ext.create(MyApp.views.UserEditorWindow).show();
});
Initially, our app.js file instructs Ext JS to add a path for the MyApp namespac
e. We do this via the Ext.loader.setPath call, passing in the namespace as the f
irst argument, and the relative path to the page being loaded.
Next, we call Ext.onReady, passing in an anonymous function, which contains a ca
ll to Ext.create. Ext.create is responsible for lazy instantiating classes with
Ext JS 4.0. We pass in the String representation of our UserEditorWindow class t
o be instantiated. Since we dont need a reference to the instance of our class an
d want to show it immediately, we chain a show method call.
If we view this in our page (http://moduscreate.com/senchaarticles/01/pass1.html
), we see that the UI renders, but its pretty slow and we get a warning message i
nside of FireBug from Ext JS!
004
Ext JS barks at us because were not using the Loader system in the most optimized
way. Well revisit this issue in a second. However, this is a great learning oppo
rtunity that we should capitalize on!
Ive configured my FireBug instance to display XHR requests inside of the console,
which allows me to see all such requests without having to switch to the Net ta
b. This gives us chance to filter though all of the Ext JS classes loaded, to wa
tch the class dependency system work, as weve instructed it to do!
Simply type in User in the FireBug console filter and youll see how it all comes to
gether.
005

As we can see, the UserEditorWindow class is first loaded, which requires the Us
erGridPanel. The UserGridPanel requires the UserStore and UserModel classes. Las
tly, the UserFormPanel class is loaded.
I mentioned earlier that Ext JS barked because were not using the Loader system i
n the most optimized way. This is because dependencies identified after Ext.onRe
ady has fired are loaded via synchronous XHR, which is not the most efficient wa
y and is not easy to debug at all.
To remedy this issue, well have to modify app.js to instruct Ext JS to load our c
lasses in a way that is both performant and easier to debug
Ext.Loader.setPath(MyApp, js/MyApp);
Ext.require(MyApp.views.UserEditorWindow);
Ext.onReady(function() {
Ext.create(MyApp.views.UserEditorWindow).show();
});
To enable faster loading of our classes and afford a better debugging experience
, we simply have to add a call to Ext.require above our Ext.onReady, instructing
Ext JS to require our UserEditorWindow class. Doing this allows Ext JS to injec
t script tags to the HEAD of the document, allowing resources to load before Ext
.onReady fires.
Visit http://moduscreate.com/senchaarticles/01/pass2.html to see this working. A
fter loading the page, youll notice that Ext JS will no longer fire warning messa
ges to the console.
What weve done is enable lazy loading of Ext JS framework and our application cla
sses. While this is the best for debugging, the page render times can be very pa
inful for rapid debugging sessions. Why you ask?
The simple answer is that the number of resources loaded is immense. In our exam
ple, Ext JS makes 193 total requests to the web server for JavaScript resources,
most of which are cached.
006
We created six JavaScript files (five classes and app.js). That means that to lo
ad the required Ext JS files, the browser had to make 187 requests. This solutio
n is viable but not ideal for many and works best when youre developing in a loca
l dev environment.
To remedy this issue, we can create a hybrid situation, where we load the entire
framework via ext-all-debug and then load our classes dynamically. To do this,
well need to modify two files.
First, well need to modify our index.html to include ext-all-debug.js instead of
ext-debug.js
<script type="text/javascript" src="js/ext-4.0.1/ext-all-debug.js"></script>
Next, well need to modify app.js to enable Ext Loader.
(function() {
Ext.Loader.setConfig({
enabled : true,
paths : {
MyApp : js/MyApp
}
});

Ext.require(MyApp.views.UserEditorWindow);
Ext.onReady(function() {
Ext.create(MyApp.views.UserEditorWindow).show();
});
})();
We enable Ext Loader by calling Loader.setConfig, passing in an anonymous object
, which has its enabled property set to true and our namespace set to path mappi
ng.
By modifying our app.js file, we allowed our application to load and render in j
ust over a second in a local dev environment
007
And there you have it! We created a simple application allowing us to use the ne
w Ext JS class dependency system as well as Loader. You may download these lab f
iles via http://moduscreate.com/senchaarticles/01/files.zip.

Das könnte Ihnen auch gefallen