Ext Js
Ext Js
Application using
Ext Js
By Dattu Dave
Sencha generate command is use to create an directory structure of Ext Js for that you must
require a directory of Ext Js thats why we change our current location in terminal to Ext Js
The directory structure of Ext Js follows MVC architecture, MyApp is the name of the
namespace of our application, meaning that every class we create is going to start with MyApp,
as for example: MyApp.model.Student, MyApp.view.Result, and so on. And the last argument
passed to the command is the directory where the application will be created. In this case it is
inside a folder named result, which is located inside the htdocsfolder.
On first line of the previous code we have the Ext.application declaration. This means that our
application will have a single page and the parent container of the app will be the Viewport. The
Viewport is a specialized container representing the viewable application area that is rendered
inside the body tag of the HTML page (<body></body>). It also manages the application's size
inside the browser and manages the window resizing.
Inside Ext.application we can also declare models, views, stores, and controllers used by the
application. We will add this information to this file as we create new classes for our project.
We need to declare the name of the application MyAPP which will be the namespace.
We can also create a launch function inside Ext.application. This function will be called after
all the application's controllers are initialized and this means that the application is completely
loaded. So this function is a good place to instantiate our main view. For now, we will only add
console.log, which just prints on the browser's JavaScript interpreter console to verify if the
application was loaded successfully.
To execute this application on the browser, we can access http://localhost/result, and we will
get the following output in console press(CTRL + SHIFT + I ) in chrome or (CTRL+SHIFT + K)
in firefox:
When working with large Ext JS applications, it is normal to have a small delay when loading
the application. This happens because Ext JS is loading all the required classes to have the
application up and running and meanwhile, all the users see is a blank screen, which can be
annoying for them. A very common solution to this problem is to have a loading page, also
known as a splash screen.
So let's add a splash screen to our application that looks like the following:
First we need to understand how this splash screen will work. At the moment the user loads the
application and the loading screen will be displayed. The application will show the splash screen
while it loads all the required classes and code so the application can be used.
We already know that the application calls the launch function when it is ready to be used. So we
know that we will need to remove the splash screen from the launch method. The question now
is where inside Ext.application can we call the splash screen? The answer is inside the init
function. The init function is called when the application boots so it gives some time for all
required code to be loaded and after that the launch function is called.
Now that we know how the splash screen will work, let's implement it.
Inside Ext.application, we will implement a function called init:
result/app.js
Ext.application({
name: 'MyApp',
init: function() {
splashscreen = Ext.getBody().mask('Loading Please Wait', 'splashscreen');
},
launch: function() {
console.log('launch');
}
});
All we need to do is apply a mask into the HTML body of the application (Ext.getBody()), and
that is why we are calling the mask method passing the loading message ("Loading Please
Wait") and applying a CSS, which will be loading gif and is already part of the Ext JS CSS
("splashscreen"). The mask method will return Ext.dom.Element, which we will need to
manipulate later (remove the mask from the HTML body) and for this reason, we need to keep a
reference to Ext.dom.Element and we will store this reference inside an attribute of
Ext.application:
result/app.js
Ext.application({
name: 'MyApp',
splashscreen: {},
init : function()
{
},
..
});
With the code of the init method only, we will have a loading screen as the following:
If this is all you need that is ok. But let's go a little bit further and customize the loading screen
adding a logo image so it can look like the first image of this topic, which is our final output.
First, we need to create a CSS file which will contain all the CSS for our application. First create
css folder inside result/resources/ and then create css file We will name it as app.css and put it
inside a result/resources/css/ folder:
Inside resources we will also create an images folder with the Attuneuniversity logo image.
We also must not forget to add the new CSS file into result/index.html:
<link rel="stylesheet" href="resources/css/app.css">
Now add following things to result/resources/css/app.css file we just created
.x-mask.splashscreen {
background-color: #efefef;
opacity: 1;
}
.x-mask-msg.splashscreen,
.x-mask-msg.splashscreen div {
font-size: 16px;
font-weight: bold;
padding-top : 17px;
padding-right : 40px;
border: none;
background-color: transparent;
background-position: top center;
}
.x-message-box .x-window-body .x-box-inner {
min-height: 93px !important;
}
.x-splash-icon {
background-image: url('../images/logo.png') !important;
background-repeat : no-repeat;
margin-top: -30px;
margin-bottom: 15px;
height: 100px;
width : 200px;
}
We will be adding a new CSS style to the loading DIV tag. Note that the following styles from
our app.css file will be applied: .x-mask.splashscreen and .x-mask-msg.splashscreendiv. This
will going to change the font of the "Loading Please Wait" message.
Now we will add the following code in the init function inside result/app.js:
init: function() {
splashscreen = Ext.getBody().mask('Loading Please Wait' , 'splashscreen');
splashscreen.addCls('splashscreen');
Ext.DomHelper.insertFirst(Ext.query('.x-mask-msg')[0], {
cls: 'x-splash-icon'
});
},
After we execute the previous code, we will have an output exactly as the image we showed at
the beginning of this topic.
Now we already have the splash screen being displayed. We need to work on the launch function
to remove the splash screen after all the code the application needs is loaded, otherwise the
loading message will be there indefinitely!
To remove the splash screen the only code we need to add to the launch function is the following
one, which is removing the mask from the HTML body:
result/app.js
Ext.getBody().unmask();
However, removing the mask abruptly is not nice because the user cannot even see the loading
message. Instead of only removing the mask, let's give the user 2 seconds to see the loading
message after the application is ready:
result/app.js
var task = new Ext.util.DelayedTask(function() {
Ext.getBody().unmask();
});
task.delay(2000);
To do so, we are going to use the DelayedTask class, which is a class that provides a chance of a
function to be executed after the given timeout in milliseconds. So in the case of the task, we are
removing the mask from the HTML body after two seconds of timeout (2,000 milliseconds).
If we test the output right now, it works, but it is still not nice for the user. It would be even better
if we can add an animation to the masking. So we will add a fade out animation (which animates
the opacity of an element from opaque to transparent) and after the animation we will remove the
masking (inside the Ext.util.DelayedTask function).
result/app.js
splashscreen.fadeOut({
duration: 1000,
remove:true
});
After we execute this code, notice that the loading message is still being displayed.Only the first
DIV tag with the class splashscreen was faded out. We need to also fade out the DIV tag with
class x-mask-msg splashscreen that contains the logo and the loading message.
result/app.js
splashscreen.next().fadeOut({
duration: 1000,
remove:true
});
After the loading mask is removed, we need to display the initial component of our application.
We will be showing a main screen that we will implement in the next. For now, we will add a
console message just to know where we need to call the initial component. The complete code
for the launch function will be the following :
result/app.js
launch: function() {
console.log('launch');
var task = new Ext.util.DelayedTask(function() {
splashscreen.fadeOut({
duration: 1000,
remove:true
});
splashscreen.next().fadeOut({
duration: 1000,
remove:true,
listeners: {
afteranimate: function(el, startTime, eOpts ){
// Here we put the code to display Our Main Screen
}}
});
Ext.getBody().unmask();
});
task.delay(2000);
}
});
Header
Student Grid
Toolbar For Student Grid
Chart
Toolbar for Chart
Chart comes Here
Footer
This is how we create main page of our application we are dividing in to four parts Header,
Student Grid, Chart and last Footer
Now lets create a view port for that Create a file called MyViewport.js in result/app/view/
folder
result/app/view/MyViewport.js
Ext.define('MyApp.view.MyViewport', {
extend: 'Ext.container.Viewport',
alias: 'widget.myviewport',
layout: {
type: 'vbox' ,
align : 'stretch'
},
items: [
{
xtype: 'container',
layout : 'fit',
height: 50,
style: 'border-bottom: 4px solid #4c72a4;background-color : #B0C4DE',
html: '<div id="titleHeader">Result<span style="font-size:12px;"> - Student Result
Available Here</span></div>'
},
{
xtype: 'container', //Grid Panel Comes Here
flex : 1,
layout : 'fit',
style: 'background-color: #dedede;'
},
{
xtype: 'container',//Chart Panel Comes Here
flex : 2,
autoScroll : true,
},
{
xtype: 'container',
layout : 'fit',
height: 30,
style: 'border-top: 1px solid #4c72a4;background-color : #B0C4DE',
html: '<div id="titleHeader"><center><span style="font-size:10px;">Demo of Student
Result</span></center></div>'
}
]
});
And we get following output:
alias: 'widget.myviewport',
this is we created an alias for our class
MyApp.view.MyViewport so we can use alias for the class so we can use it using alias
name myviewport
After that we create an layout properties here we use vbox layout it means all the
components are arranged in the vertical format and also we are using stretched align so each
component will take all space vertically
result/app/model/Student.js
Ext.define('MyApp.model.Student', {
extend: 'Ext.data.Model',
fields: [
{
name : 'id'
},
{
name: 'name'
},
{
name: 'age'
},
{
name: 'email'
},
{
name: 'sem'
},
{
name: 'photo'
},
{
name: 'Result'
}
]
});
We create a student model which is extend from Ext.data.Model. This model is having fields
required are id (student id), name, age, email, sem, photo and result details
result/app/store/Students.js
Ext.define('MyApp.store.Students', {
extend: 'Ext.data.Store',
requires: [
'MyApp.model.Student'
],
model: 'MyApp.model.Student',
autoLoad : true,
proxy: {
type: 'ajax',
url: 'php/studentlist.php',
reader: {
type: 'json',
root: 'data'
}
}
});
These are the two php file we are using to fetch the data
$r['Result'] = array();
while ($item = $nodes->fetch_assoc())
{
$r['Result'][] = $item;
}
}
$folder[] = $r;
}
}
}
$resultdb->close();
$mysqli->close();
So we created a php files which will give the data in json format like this
{"data":[{"id":"1","name":"Raj
Patel","age":"17","email":"student1@demosite.com","sem":"1","photo":"1.jpg","Result":[{"sub":"
Maths","marks":"85"},{"sub":"Science","marks":"80"},{"sub":"English","marks":"72"}]},{"id":"2
","name":"Vishal
Joshi","age":"17","email":"student2@demosite.com","sem":"1","photo":"2.jpg","Result":[{"sub":"
Maths","marks":"25"},{"sub":"Science","marks":"65"},{"sub":"English","marks":"78"}]},{"id":"3
","name":"Riyaz
Khan","age":"17","email":"student3@demosite.com","sem":"1","photo":"1.jpg","Result":[{"sub":"
Maths","marks":"46"},{"sub":"Science","marks":"52"},{"sub":"English","marks":"88"}]},{"id":"4
","name":"Sonali
Sharma","age":"17","email":"student4@demosite.com","sem":"1","photo":"4.jpg","Result":[{"sub
":"Maths","marks":"88"},{"sub":"Science","marks":"26"},{"sub":"English","marks":"56"}]},{"id"
:"5","name":"Pankaj
Shah","age":"17","email":"student5@demosite.com","sem":"1","photo":"5.jpg","Result":[{"sub":"
Maths","marks":"90"},{"sub":"Science","marks":"89"},{"sub":"English","marks":"56"}]}]}
},
]
});
We create a grid panel Extend it from Ext.grid.Panel
Giving alias name to studentlist and frame property to false
Then we assign store Students i.e. MyApp.store.Students which will fetch the student data
Then we create a columns i.e name, age, sem, email and photo in columns dataIndex value
must match the field we created in model and fields which are return by php in json format
In photo filed we created a function so when this column is renderd it will give an
image(profile photo) so we can see a profile photo in the grid
this.control({
"studentlist": {
render: this.onRender,
},
});
if (!Ext.getStore('Students')) {
console.log ("store created");
Ext.create('MyApp.store.Students');
}
},
onRender: function(component, options) {
component.getStore().load();
},
});
We create a controller for the grid which is extend from the Ext.app.Controller
In this flie we create a all functionality and handles all events
Then we have the views declaration, which is where we are going to declare all the views that
this controller will care about.
we will create a reference for the studenlist component, where xtype is studentlist and we will
name ref as studentList. With this ref declared, the controller will automatically generate the
getStudentList() method for us to retrieve the reference of this component.
Next, we have the init method declaration. The init method is called before the application
boots, before the launch function of Ext.application (app.js). The controller will also load the
views, models, and stores declared inside its class.
Then we have the control method configured. This is where we are going to listen to all events
we want the controller to react.
Then we listen a event of render of Grid Panel stdentlist by creating function onRender when
a grid panel Studentlist is render this function will call
In that function we load the store of the grid so in grid we can see the data
{
xtype: 'students', //Grid Panel Comes Here
flex : 1,
layout : 'fit',
style: 'background-color: #dedede;'
},
]
});
Change the xtype to studentlist where we give comment gridpanels come here for that we
have to add requires property in MyViewport.js file because we want to use this class
Ext.application({
name: 'MyApp',
splashscreen: {},
requires: [
'Ext.data.proxy.Ajax',
'MyApp.view.MyViewport'
],
controllers :[
'Students',
],
init : function(){
});
We have to put Ext.data.Ajax in requires otherwise it will give warning and we must not fotgot
to put controller we just created i.e.
So after all this changes we get following output:
First we create a model for chart we will display subject and marks in charts so in model we
define subject and marks
So create a file called StudentChart.js in result/app/model folder.
result/app/model/StudentChart.js
Ext.define('MyApp.model.StudentChart', {
extend: 'Ext.data.Model',
fields: [
{
name: 'sub'
},
{
name: 'marks'
}
]
});
We create a model for chart with fields sub and marks
}, cfg)]);
}
});
So we create a store for chart here we dont give any php file because we are going to use the
data fetch from stdentlist.php
Then we are going to display the mark inside column so we put label properties
open
the
Ext.define('MyApp.controller.Students', {
extend: 'Ext.app.Controller',
views: [ 'Students' ],
requires :
['MyApp.view.MyViewport',
'MyApp.view.ColumnChart',
'MyApp.util.Alert'
],
refs: [
{ ref: 'studentList',
selector: 'studentlist'
},
{ ref: 'ColumnChart',
selector: 'columnchart'
},
],
stores: [
'Students',
'StudentChartStore'
],
init: function(application) {
this.control({
"studentlist": {
render: this.onRender,
select : this.onGridpanelSelect
}
});
if (!Ext.getStore('Students')) {
Ext.create('MyApp.store.Students');
}
},
onRender: function(component, options) {
component.getStore().load();
},
onGridpanelSelect: function(rowmodel, record, index, eOpts) {
var qualityData = record.get('Result');
var maths = qualityData[0]['marks'];
var science = qualityData[1]['marks'];
var English = qualityData[2]['marks'];
var per = parseInt(maths) + parseInt(science) + parseInt(English);
per = parseFloat(per/3).toFixed(2);
if(maths < 40 || science < 40 || English <40)
{
var failsub = "";
if(maths < 40)
{failsub = "Maths";}
if(science < 40)
{failsub = failsub +" Science";}
if(English < 40)
{failsub = failsub +" English";}
MyApp.util.Alert.msg("Bad Luck", record.get('name') + " Failed The Exam
with" + per + "% in " + failsub);
}
else
{
MyApp.util.Alert.msg("Congratulation", record.get('name') + " Passed The
Exam with" + per + "%");
}
var chart = this.getColumnChart();
chart.store.loadData(qualityData);
},
});
We make changes to the controller first we added MyApp.view.ColumnChart and
MyApp.util.Alert in require property because we will use this classes in our controller
We are make one class Alert.js and put it inside result/app/util/ folder here we are not going to
show the code of that class it is used for display the message
Then we add columnchart in refs so we added reference of it and getColumnChart() method
automatically generated
Inside this.control function we add fuction onGridPanelSelect on select event of gridpanel
In onGridPanelSelect function first we fetch the result data from the store of the grid in
qualityData variable
From that result data we fetch marks of Maths, English, and Science and we put the logic of
calculating percentage and display the message whether student is passed or not
Finally we get an instance of chart by getCoulmnChart() method and load the store of the chart
by result data of grid store which contain marks and subject as json data. Thats why we can see
the chart of particular student selected in the grid
{
xtype: columnchart, //Chart Panel Comes Here
flex : 1,
layout : 'fit',
style: 'background-color: #dedede;'
},
]
});
Change the xtype to columnchart where we give comment Chart Panel Comes Here for that
we have to add requires property in MyViewport.js file because we want to use this class
Ext.application({
name: 'MyApp',
enableQuickTips : true,
splashscreen: {},
views : [
'Main',
'Viewport',
'MyViewport'
],
requires: [
'MyApp.view.MyViewport',
'Ext.data.proxy.Ajax',
'MyApp.util.Util',
'Ext.layout.container.Card',
'Ext.chart.series.Pie',
'Ext.chart.series.Column',
'Ext.chart.axis.Numeric',
'Ext.chart.axis.Category',
'MyApp.view.PieChart',
'MyApp.view.ColumnChart'
],
controllers :[
'Students',
],
init : function()
{
});