Beruflich Dokumente
Kultur Dokumente
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.