Monday, 8 December 2014

Ext JS Interview Question and Answers

1.How to create your code in MVC Structure.

Angular JS Drawback ::

Its main drawback is a steep learning curve, largely due to its
poor documentation and code examples.


Other Libraries ::


Libraries like jQuery and Prototype are well suited to smaller applications.

Why ExtJS ::

If you’re looking at developing an enterprise application that deals
with graphs, data grids, communicating with a server, and exchanging lot of data, drag and drop behavior etc, Ext JS 4 is a pretty good candidate.

Here’s a list of features in Ext JS 4

•     Object-Oriented flavor- JavaScript has never been taken seriously as a programming
language. We never learn JavaScript the way we have learned Java or C# or Ruby. Developers
who come from an OO background find it difficult to shift to the functional style of coding; so JavaScript, as a functional programming language, poses adaptability issues for OO
developers. Ext JS 4 lends an OO flavor to the JavaScript language. So developers who are
accustomed to coding in OO languages will be in tune with the Ext JS 4 API.

•     Rich UI controls- Ext JS 4 provides a rich set of UI components, like any other JavaScript
library. The UI controls include different types of form components, and data components
such as grid, tree, and charts. You have to write a few lines of code in JavaScript even to create
a simple label or a textbox. The programmatic approach to using UI components paves the
way for extending and customizing them.

•     Support for HTML 5- HTML 5 provides a set of features like a new set of UI tags, multimedia
capabilities without depending on third party plugins, data storage facilities, web sockets, web
workers, Canvas API for drawing, GeoLocation, and working with history. The Ext JS 4 API
supports HTML 5 tags, working with local storage and session storage, drawing, etc.

•     MVC architecture- Modularity has always been an issue in JavaScript libraries. Maintenance is a nightmare in web applications developed using JavaScript, no matter what framework we use. Incorporating new behavior into existing code is a tedious task. Very few libraries in
JavaScript take care of modularity. Ext JS 4 stands apart in this respect. One of the reasons for Ext JS 4’s popularity is the support that it offers for implementing MVC. The complete code can be organized into folders and files following the MVC architecture. Making changes and
testing becomes easier because of this.

•     Theming and Styling- Creating stylesheets by writing vanilla CSS code for an entire application can be very frustrating: it’s an uphill task. Ext JS 4 gives us themes that can be used in applications. You can modify those themes to suit your needs. But we don’t have to write CSS code to do that. Ext JS 4 relies upon SASS (Syntactically Awesome StyleSheets) scripts
for styling. The style sheets for the UI controls are available as SASS files which we can play with. The SASS scripts are then compiled to CSS files using a Ruby script called Compass. This makes styling our applications much easier.

•     Documentation- Sencha maintains very good API documentation for all the versions. The documentation is very well organized and includes nice reference material, something I have missed while working with other JavaScript libraries. It has good code examples that illustrate the usage of many features.

this.callParent :: You can call a base class method from the derived class method in Ext JS 4 by writing this.callParent(arguments);

The arguments passed to the Manager’s work function can be supplied to the Employee’s work function by using
the arguments keyword in JavaScript as shown below.

this.callParent(arguments);

You can extend a class and override the constructor as shown below. You can invoke the base class
constructor using this.callParent method.
Ext.define("Manager",{
   extend : "Employee",
   constructor : function(cfg){
       this.callParent(arguments);
   }
});

Inheriting a UI component class and overriding the constructor
is not a recommended practice


Create a button field in Extjs


If you have to display a Hello World button, we’ll create an object of the Ext.Button class and render it to the document body as
shown below.

Ext.onReady(function () {
   Ext.create("Ext.Button",{
     text : "Hello World",
     renderTo : Ext.getBody()
   });
});

One noteworthy aspect of Ext JS 4 code is its object-oriented approach. All the UI components are available as classes, and we just need to create instances of the classes and render them.

Classes and Objects

You can define a new class in Ext JS 4 using the Ext.define method. You pass in the class name and the object where
you define the attributes and behavior of the class as arguments to the Ext.define method.

Ext.define("Book",{});

If you have worked with Ext JS 3 or the earlier versions, you will notice that the Ext.define method incorporates the functionalities of using Ext.reg, Ext.ns, and Ext.extend methods.

Ext.create("Book");

You can specify a fully qualified class name with a root namespace and package names included as shown below.

Ext.define("DuraSoft.tech.extjs4.Book",{});

In traditional OO languages the new keyword is used to create objects. You can use new to create objects in Ext JS 4 also.

var book1 = new DuraSoft.tech.extjs4.Book();

The Ext.create("classname") method dynamically loads all the JavaScript files that the classname is dependent on before creating an instance, whereas this is not possible when you use the new keyword.

Constructor ::

Constructor is the first function that’s called when an object is created. You can define constructors in our classes using the special property constructor. The constructor property is wired to a function that gets invoked when
an object is created using Ext.create.

Ext.define("DuraSoft.tech.extjs4.Book",{
   constructor : function(){
       console.log("Book created");
   }
});

Config

Ext JS 4 provides a config section for every class where you can list the attributes of the class with default values.
The object can be created by initializing the attributes in which you are interested.

Ext.define("DuraSoft.tech.extjs4.Book",{
  config : {
    title : "",
    price : -1,
    authors: []
 },
constructor : function(cfg){
   this.initConfig(cfg);
 }
});

The config section is initialized in the constructor by calling the initConfig method

Loading Dependencies ::

Ext JS 4 introduces the concept of dynamic loading of the dependent JavaScript files. You can specify the classes that your code is dependent on and the appropriate class files are loaded dynamically.

Ext.Loader.require("Ext.button.Button");

(or)

Ext.require("Ext.button.Button");

Ext.require loads the Button.js file and recursively the Button’s dependent files as well.

There’s another way of specifying the loading information by using the requires property in a class, as shown below.

Ext.define("MyPanel",{
   requires : ["Ext.button.Button"]
});

DoLayout  ::

doLayout method triggers the container to recalculate the layout and refresh itself.

Down ::

This method, similar to the up method in Component class, is used to navigate to the descendants of the container
that matches the expression passed as an argument. For example if you have a container, say container1, that has a
button calling container1.down("button") walks down the container and returns the button component that’s a
child or grandchild or any descendant.

Types of Columns ::

Ext.grid.column.Action actioncolumn Represents a column that renders a collection of icons each with a click handler. Usually used to perform
operations like add, edit, delete, etc.

Ext.grid.column.Date datecolumn :: Used to render a date formatted column

Ext.grid.column.Number numbercolumn :: Used to render a number formatted column

Ext.grid.column.CheckColumn checkcolumn Represents a checkbox column

Ext.grid.column.Boolean
booleancolumn Used to display a boolean value formatted column

Ext.grid.column.TemplateColumn
templatecolumn Used to specify an XTemplate instance to format the data

Ext.grid.RowNumberer rownumberer Render row numbers

Ext.create("Ext.grid.Panel", {
store: movieStore,
height : 150,
title : "Tom Hanks collection",
columns: [
{xtype : "rownumberer"},
{
    text: 'Movie',
    dataIndex: 'title',
},
{
    text: 'Rent',
    dataIndex: 'rent',
    xtype : "numbercolumn",
    format : "0.00"
},
{
    text: 'Buy',
    dataIndex: 'buy',
    xtype : "numbercolumn",
    format : "0.00"
},
{
    text : "Blue-ray",
    dataIndex : "bluerayFormat",
    xtype : 'booleancolumn',
    trueText : "Available",
    falseText : "Not available"
},
{
   text: 'DVD release date',
   dataIndex: 'dvdReleaseDate',
   xtype : "datecolumn",
   format : "M d, Y"
},
{
   text : "Wiki",
   xtype : "templatecolumn",
   tpl : "<a href='{wikipedia}' target='_blank'>Read</a>"
},
{
   text: 'Add',
   xtype : "actioncolumn",
items : [
{
    tooltip:"Edit",
   icon : "edit.jpg",
   handler : function(grid,rowNum,colNum){
     //Edit logic
}
},
{
    tooltip:"Delete",
    icon : "delete.jpg",
    handler : function(grid,rowNum,colNum){
        //Delete logic
   }
}
},
]
});

Grid Plugins :: 

The base class for any plugin is Ext.AbstractPlugin. The grid panel has behaviors like editing, grouping, drag and drop, etc.

Ext.grid.plugin.Editing Used for editing the row and cells of the grid
Ext.grid.plugin.RowExpander Used for creating expandable rows
Ext.grid.plugin.BufferedRenderer Used to render large number of records in a grid
Ext.grid.plugin.DragDrop Implements the drag and drop functionality in a grid
Ext.grid.feature.Feature This plugin acts as a base class for a number of features like grouping, summary, etc.

Each plugin has an alias name known as ptype similar to xtype. You can configure the plugin using its ptype or by using Ext.create() method.

 The rowediting and cellediting plugins provide four events beforeedit, edit, canceledit, and validateedit.
The validateedit event is called before updating the underlying record in the store

Ext.grid.plugin.Editing ::

This plugin provides the grid editing behavior. This plugin class has two subclasses, Ext.grid.plugin.CellEditing and

Ext.grid.plugin.RowEditing, to either edit the cell or the row. The working of this plugin depends on a configuration  attribute of the grid class called selType. The selType attribute denotes the selection model. You can select a cell or a row
in a grid. The value of selType can either be cellModel or rowModel.

plugins : [
Ext.create("Ext.grid.plugin.RowExpander",{})
]

You can use the ptype as shown below.

plugins : [
{
ptype : "rowexpander"
}
]


CellEditing ::

You can edit the cell of the grid using this plugin. The ptype or the alias name of this plugin class is cellediting.

This plugin when added to the grid with the selType as cellModel, converts the cell to editable format when the cell is double-clicked.

Ext.create("Ext.grid.Panel", {
store: movieStore,
height : 150,
title : "Tom Hanks collection",
selType : "cellmodel",

plugins : [
{
ptype : "cellediting",
clicksToEdit : 2
}
]


Ext.grid.plugin.RowExpander ::

This plugin class provides the row in the grid to have contents that can be collapsed and expanded. It uses the RowBody feature


Ext.create("Ext.grid.Panel", {
store: movieStore,
height : 300,
title : "Tom Hanks collection",
plugins: [
{
   ptype: 'rowexpander',
   rowBodyTpl : [
      '<p>{description}</p>'
   ]
}
]


Ext.grid.plugin.BufferedRenderer ::

If you have a grid that displays a large number of records, scrolling the grid vertically may have a visual impact. When you try to scroll down a grid, the current viewable set of rows in the grid have to be replaced with a new set of data has to be shown in the grid. In the earlier versions of Ext JS 4, this feature was implemented by re-creating all the rows every time you scroll. In other words, the grid was being redrawn everytime. This may lead to a delayed response or a visual blur or sometimes the grid may even become unresponsive for a few seconds or more.


The latest version of Ext JS, 4.2 solves this problem by not replacing or re-rendering rows when you scroll. It just adds or removes the rows to the grid without re-rendering the entire grid panel. What they do is create a set of rows before and after the current viewable set of rows and store them in a buffer. When you scroll down the buffered set of rows is shown in the grid.


You can configure the grid with the BufferedRenderer plugin to configure the buffered rendering of the rows in the grid. The buffered rendering is also popularly known as infinite scrolling. 


The Plugin has attributes like trailingBufferZone and leadingBufferZone to specify the number of rows that have to be buffered before and after the current viewable set of rows. 


It also provides an attribute numFromEdge that indicates the number of rows from the edge of the table. Say the numFromEdge is 5, and if the viewable area is scrolled till you have 5 rows from the edge of the table, then the grid is
appended with newer set of rows.


You can configure the plugin with the grid as shown below.


plugins : [
{
ptype :"bufferedrenderer",
trailingBufferZone : 10,
leadingBufferZone : 20,
numFromEdge : 7
}
]


Grid Features ::

Ext.grid.feature.Feature class is a grid plugin that provides functionalities like grouping, summary etc.,


Ext.grid.feature.RowBody: Used for adding additional contents to a grid row
Ext.grid.feature.Grouping: Used to create grouped records
Ext.grid.feature.Summary: Used for displaying summary data in a grid
Ext.grid.feature.GroupingSummary: Used to display summary data for each grouped set of records 


Ext.grid.feature.RowBody

RowBody feature is used add additional contents to a grid row. In other words, it’s used to implement a nested grid. It generates an additional <tr> element. The ftype of RowBody class is rowbody. The RowBody feature is pretty similar to
the RowExpander plugin that we discussed earlier, the only difference being the lack of the expand/collapse functionality provided by RowExpander. You have to configure the getAdditionalData() method of the feature to return the contents of
the additional row. Here’s how you create a grid with rowbody feature.

Ext.create("Ext.grid.Panel", {
store: movieStore,
height : 350,
title : "Tom Hanks collection",
features: [
{
   ftype: 'rowbody',
  getAdditionalData : function(data){
     return {
        rowBody : "<p>" + data.description + "</p>",
        rowBodyColspan : 3
    };
}
}],
columns: [
{
    text: 'Movie',
    dataIndex: 'title',
},
{
    text: 'Rent',
    dataIndex: 'rent',
},

{
    text: 'Buy',
   dataIndex: 'buy',
}
]
});


Ext.grid.feature.Summary ::

The summary feature is a simple plugin used to display summary information of the records for each column. The summary for each column is specified using two properties, summaryType and summaryRenderer. The summaryType is a
mathematical calculation attribute. You can set the summaryType to be one of the values in this list: sum, count, average, max, min. The summaryRenderer is a function that formats the display information. Figure 6-15 shows the grid with a
summary feature. 


Ext.create("Ext.grid.Panel", {
store: movieStore,
height: 350,
title: "Tom Hanks collection",
features: [
{
   ftype: 'summary'
}],
columns: [
{
    text: 'Movie',
    dataIndex: 'title',
    summaryType: "count",
    summaryRenderer: function (value) {
    return "<b>Movie count: " + value + "</b>";
}

},
{
    text: 'Rent',
    dataIndex: 'rent',
    summaryType: "average",
    summaryRenderer: function (value) {
    return "<b>Average rent: $" + Ext.Number.toFixed(value, 2) + "</b>";
}
}, 

{
     text: 'Buy',
     dataIndex: 'buy',
     summaryType: "sum",
     summaryRenderer: function (value) {
     return "<b>Total : $" + Ext.Number.toFixed(value, 2) + "</b>";
}
}
]
});


Ext.grid.feature.Grouping ::

Ext.grid.feature.Grouping plugin is used to group rows in a grid based on the group field that you configure in the data store. Let’s modify our movie store to add a grouping field as shown below.

var movieStore = Ext.create("Ext.data.Store", {
fields: ["title", "rent", "buy", "rating"],
groupField : "rating",
data: [
   { title: "Forrest Gump", rent: 2.99,buy:6.99,rating:"PG-13"},
   { title: "Cast Away", rent: 3.99,buy:13.46,rating:"PG-13"},
   { title: "Apollo 13", rent: 3.99, buy: 7.99, rating: "PG" },
   { title: "The Green Mile", rent: 1.99, buy: 9.99, rating: "R" },
   { title: "Sleepless in Seattle", rent: 1.99, buy: 11.97, rating: "PG" },
   { title: "Toy Story 3", rent: 1.99, buy: 14.99, rating: "G" },
]
});

We’ve introduced a rating field that’ll serve as the groupField. Let’s display the grid where records are grouped
based on their rating. Here’s the grid where we’ve used the grouping feature.

Ext.create("Ext.grid.Panel", {
store: movieStore,
height: 350,
title: "Tom Hanks collection",
features: [
{
    ftype: 'grouping',
    groupHeaderTpl : "Rating: {name}",
    collapsible : false,
   showSummaryRow : true
}
],
columns: [
{
   text: 'Movie',
   dataIndex: 'title'
},

{
   text: 'Rent',
   dataIndex: 'rent'
},
{
   text: 'Buy',
   dataIndex: 'buy'
}
],
renderTo: Ext.getBody()
});


Ext.grid.feature.GroupingSummary ::

Ext.grid.feature.GroupingSummary plugin is used to add summary information for the group rows. It’s a combination of the Grouping and Summary features. The code snippet for the grid panel with grouping summary feature is given below.

Ext.create("Ext.grid.Panel", {
store: movieStore,
height: 350,
title: "Tom Hanks collection",
features: [
{
    ftype: 'groupingsummary',
    groupHeaderTpl: "Rating: {name}",
    showSummaryRow : true
}],
columns: [
{
    text: 'Movie',
    dataIndex: 'title',
    summaryType: "count",
    summaryRenderer: function (value) {
   return "<b>Movie count: " + value + "</b>";
}
},
{
   text: 'Rent',
   dataIndex: 'rent',
   summaryType: "average",
   summaryRenderer: function (value) {
   return "<b>Average rent: $" + Ext.Number.toFixed(value, 2) + "</b>";
}
},
{
   text: 'Buy',
   dataIndex: 'buy',
    summaryType: "sum",
    summaryRenderer: function (value) {
   return "<b>Total : $" + Ext.Number.toFixed(value, 2) + "</b>";
}
}
],
});


1.What is Mixins?

Mixins help you to mix the behavior of different classes into your class. Your class can have the functionalities of any number of classes mixed together. It’s somewhat similar to interfaces in Java where a class can implement any number
of interfaces.
24
www.it-ebooks.infoChapter 3 ■ Understanding the Ext JS 4 API
Let’s create two classes, Aquatic and Terrestrial, with swim and walk functions, respectively.

Ext.define("Aquatic",{
swim : function(){
console.log("Swimming");
}
});

Ext.define("Terrestrial",{
walk : function(){
console.log("Walking");
}
});

We’ll create a class Reptile that can walk as well as swim. The Reptile class is created by mixing Aquatic and
Terrestrial together.

Ext.define("Reptile",{
mixins : ["Aquatic","Terrestrial"]
});

A Reptile instance can invoke the walk and swim functions.

var reptile = Ext.create("Reptile");
reptile.swim();
reptile.walk()
;

2. How to hide particular column cell in grid panel

grid.on('beforeedit', function(e) {
    if (e.record.get('phone') == "555-111-1224")
        grid.getPlugin('rowEditing').editor.form.findField('name').disable();
    else
        grid.getPlugin('rowEditing').editor.form.findField('name').enable();
});

3. How to create multiple instance in a store?

Ext.define('MyGrid', {
    define : 'Ext.grid.Panel',
    alias : 'widget.mygrid',

    title : 'My Grid',

    initComponent : function() {
        var me = this;

        Ext.apply(me, {
            store : me.buildStore()
        });

        me.callParent(arguments);
    },

    buildStore : function() {
        return Ext.create('MyStore', {
            //...
        });
    }
});





4. How to create listbox or how to list items one by one in combox box without any external plugin in extjs?
5.Difference between extjs 4 and 5?
6.Store used in tree panel
7.Event bubbling and event propagation
8.Bind in javascript
9.Event loop
10.ptype in ExtJS
11.initcomponent.
12.Absolute and anchor layout difference
13.( ) in fieldset?
   Manually force this container's layout to be recalculated. The framework uses  this internally to refresh layouts form most cases.

Types of Store ::

ArrayStore This class is used if the data is a simple array collection.

JsonStore Used when the data is in JSON format

JsonPStore Used to hold JSON formatted data loaded from different domains. This class uses the JsonPProxy class.

XmlStore You’ve an XML formatted data that needs to be loaded into a Store and XmlStore comes in here.

TreeStore Mainly used in tree control, this class is used to load hierarchical data.

DirectStore Ext Direct is a specification that paves way for communication of Ext JS 4 clients with the server
platforms. The DirectStore class uses a Direct Proxy class to talk to
the server and exchange JSON data.


 InitComponent ::

This method is invoked by the constructor. It is used to initialize data, set up configurations, and attach event handlers.

Another interesting point is that initComponent is the place where child components (for container), stores, view, templates, etc., are created. So, before calling the superclass initComponent method

The initComponent template method is an important initialization step for a Component. It is intended to be implemented by each subclass of Ext.Component to provide any needed constructor logic. The initComponent method of the class being created is called first, with each initComponent method up the hierarchy to Ext.Component being called thereafter. This makes it easy to implement and, if needed, override the constructor logic of the Component at any step in the hierarchy.
The initComponent method must contain a call to callParent in order to ensure that the parent class' initComponent method is also called.

The constructor() is the object/class before create method. And initComponent() is the component before show method.  

Failure property form submit 

The failure callback, on the other hand, can be extended to look for specific reasons why the failure occurred (for example, there was an internal server error, the form did not pass client-side validation, and so on). This is done by looking at the failureType property of the action parameter.

Ext.form.action.Action has four failureType static properties:
CLIENT_INVALID ,
SERVER_INVALID , 

CONNECT_FAILURE , and LOAD_FAILURE , which can be used to compare
with what has been returned by the server.


failure: function(form, action){
   if (action.failureType === Ext.form.action.Action.CLIENT_INVALID) {
     Ext.Msg.alert('CLIENT_INVALID', 'Something has been missed. 

         Please  Check and try again.');
   }

   if (action.failureType === Ext.form.action.Action.CONNECT_FAILURE) {
     Ext.Msg.alert('CONNECT_FAILURE', 'Status: ' + action.response.status 

       + ': ' + action.response.statusText);
  }
  if (action.failureType === Ext.form.action.Action.SERVER_INVALID) {
     Ext.Msg.alert('SERVER_INVALID', action.result.message);
  }

  if(action.failureType == Ext.form.action.Action.LOAD_FAILURE){
      Ext.Msg.alert('LOAD_FAILURE', action.result.message);
  }


An alternative to CLIENT_INVALID

The isValid method in Ext.form.Basic is an alternative method for handling
client-side validation before the form is submitted. isValid will return true when
client-side validation passes:


handler: function(){
    if (formPanel.getForm().isValid()) {
        formPanel.getForm().submit({
           url: 'submit.php'
       });
    }
}

Defining a Controller

Controllers are the glue that binds an application together. All they really do is listen for events (usually from views) and take some actions. Continuing our Account Manager application, lets create a controller. Create a file called app/controller/Users.js and add the following code:

Ext.define('AM.controller.Users', {
    extend: 'Ext.app.Controller',

    init: function() {
        console.log('Initialized Users! This happens before the Application launch function is called');
    }
});
 
Now lets add our newly created Users controller to the application config in app.js:

Ext.application({
    ...

    controllers: [
        'Users'
    ],

    ...
});
 
When we load our application by visiting index.html inside a browser, the Users controller is automatically loaded (because we specified it in the Application definition above), and its init function is called just before the Application's launch function.

The init function is a great place to set up how your controller interacts with the view, and is usually used in conjunction with another Controller function - control. The control function makes it easy to listen to events on your view classes and take some action with a handler function. Let's update our Users controller to tell us when the panel is rendered:

Ext.define('AM.controller.Users', {
    extend: 'Ext.app.Controller',

    init: function() {
        this.control({
            'viewport > panel': {
                render: this.onPanelRendered
            }
        });
    },

    onPanelRendered: function() {
        console.log('The panel was rendered');
    }
});
 
DoLayout and DoComponentLayout ::
 
The two are actually quite different. doLayout is a container method used to set the sizes of child components within the container.
 doComponentLayout is a component method used to size the elements (typically) that make up that component. 
 
RowEditing ::
 
 var rowEditing = Ext.create('Ext.grid.plugin.RowEditing', {
        clicksToMoveEditor: 1,
        autoCancel: false
 });
 
rowEditing.cancelEdit(); -> Cancel Previous edit
Define our data model ::
 
    Ext.define('Employee', {
        extend: 'Ext.data.Model',
        fields: [
            'name',
            'email',
            { name: 'start', type: 'date', dateFormat: 'n/j/Y' },
            { name: 'salary', type: 'float' },
            { name: 'active', type: 'bool' }
        ]
    });

Create a model instance :: 
 
                var r = Ext.create('Employee', {
                    name: 'New Guy',
                    email: 'new@sencha-test.com',
                    start: new Date(),
                    salary: 50000,
                    active: true
                });

                store.insert(0, r); ->Insert Record at first position in a store
                rowEditing.startEdit(0, 0); ->Editing shows at first cell and first row in a grid
                                              Panel 

1.SAAS vs CSS
2.Create single instance of store
3.Apply Template in view
4.Find particular column cell and change the value in grid panel
{
            header: 'Light',
            dataIndex: 'light',
            width: 130,
            editor: {
                xtype: 'combobox',
                typeAhead: true,
                triggerAction: 'all',
                selectOnTab: true,
                store: [
                    ['true','true'],
                    ['false','false']
                ],
        listeners: {
          select : function(field, eOpts){
             if(field.getValue()=="false"){
               alert(field.getValue());
                var rec =  gridpanel.getStore().findRecord("price","7.16");
            rec.set("price", "999");
             } 
          }
        },
                lazyRender: true,
                listClass: 'x-combo-list-small'
            }
        }
5.APP.js and Application.js
6.Debug error in extjs
  Use Firebug, ext-alldebug.js and Ext.error.handle function
7.Load and LoadRecord
  Load : Load data in the store via configured proxy
  LoadRecord :: Load data in the store from the array of model instances
  LoadData(data, boolean):: Load the array of data straight in the store
      True:: To append new records from the existing records.
      False :: To replace existing records with new one

8.Load data in a combobox using a single call
9.Viewport
10.Handle browser compatibility issue.

11.ExtJS Best Practices 

Maintain an organized project structure. Placing every view under “views” in a directory is likely to cause headaches somewhere down the line, especially if a developer unfamiliar with the project needs to find the source of a particular view.
Group views in sub-folders based on relevance and function. As the project grows and the number of views increases, more tiers should be added to your folder structure. Adding another folder in the hierarchy will have very little impact in the execution of the application, but has the potential to save some frustration.
Your source code should conform to a coding standard. A set standard will help fight against spaghetti code, promote reusability, and facilitate learning. When in doubt, the best code structure you can conform to is the ExtJS source code itself.

Ext.override

Ext.override is a function that allows you to override classes and add or change any functionality you desire. It’s important to understand that if you override a base class, the functionality will affect every instance of that class and any classes that inherit from it. There’s a good chance you will introduce a few defects in the process. Also, if you decide to upgrade to a newer version of ExtJS, there’s a chance your override will no longer work as intended.
There will be times when it is necessary to override a class. In these cases, be sure to use best practices when applying the overrides. Do not just place all of your overrides in one file and let it grow over time. Break them apart into their own succinct files and make plenty of comments to describe the reasoning behind and outcome of your changes. It will save time if another developer has to revisit that override after a long period of time.

Excessive Layouts

Layouts can be the bane of an ExtJS application’s existence. They can be triggered by adding or removing new components, changing a component’s content or size, updating a record displayed in a grid with a custom renderer, and much more.
Any time you have a code block that is making these types of changes be sure to surround it with:
suspendLayouts();
     #code causing layouts to occur
resumeLayouts(true);
Or if you are CRUDing records in a store that is causing a grid to perform multiple layouts, consider using:
gridStore.suspendEvents(); 
      #CRUD operations
gridStore.resumeEvents();

Large Grid Datasets

BufferedRenderer is a great plugin to use with grid panels when dealing with large datasets. Essentially this acts as an infinite scrolling solution and rows are only rendered onto the screen when they need to be, rather than all at once.
var grid = Ext.create('Ext.grid.Panel', { 
     //..
     autoLoad: true, 
     plugins: {
        ptype: 'bufferedrenderer',
        trailingBufferZone: 10,
        leadingBufferZone: 20,
        numFromEdge: 6
    },
    //.. 
});
The config options to note are:
- trailingBufferZone – the number of rows rendered above the table
- leadingBufferZone – the number of rows rendered below the table
- numFromEdge – the number of rows from the end of the leading or trailing buffer zones that will cause more rows to be rendered into the table

Lazy Instantiation

Attempt to lazily instantiate your items array wherever possible. A primary example would be the hidden tabs of a tabpanel. If the parent container never gets rendered, the child items aren’t instantiated. The plugin here will allow you to accomplish this.
{
    xtype: 'tabpanel',
    items: [{
        title: 'T1',
        plugins: {
            ptype: 'lazyitems',
            items: [...]
        }
},    {
        title: 'T2',
        plugins: {
            ptype:'lazyitems',
            items: [...]
        }
    }, {...}]
}

Nesting

Overnesting occurs if a component has a single item in its list, which in turn has a single item of its own that defines the rest of the components in the view. The item in the middle should be omitted completely, if the functionality remains the same. Doing so keeps the application structure simple to help reduce the DOM burden and speed up your application.
This bookmarklet helps to automate the search and point you toward problem areas where your application might have some unneeded nesting. A simple way to run this is to copy and paste the code from Gist into your browser’s developer console while the application is running. You will notice areas of the app highlight in red and any problem areas will be logged in the console.

Moving Forward

Sencha continues to improve the features and functionality of ExtJS, with a focus on performance. Upcoming plugins such as Ext.grid.plugin.CellUpdating will help allow developers to sidestep some of the performance issues that can occur today. However, it will always be up to the developer to use ExtJS the right way in order to get the most out of the framework. Being proactive and learning about the potential pitfalls early on will help clear the road of bugs and open the way to progress.


1. Excessive or unnecessary nesting of component structures

One of the most common mistakes developers make is nesting components for no reason. Doing this hurts performance and can also cause unappealing aesthetics in the app with oddities such as double borders or unexpected layout behavior. In example 1A below, we have a panel that contains a single grid. In this case, the panel is unnecessary. As shown in example 1B, the extra panel can be eliminated. Remember that forms, trees, tab panels and grids all extend from Panel, so you should especially watch for unnecessary nesting conditions whenever using these components.
 
items: [{
    xtype : 'panel',
    title: ‘My Cool Grid’,
    layout: ‘fit’,
    items : [{
        xtype : 'grid',
        store : 'MyStore',
        columns : [{...}]
    }]
}]
 
Example 1A. BAD: The ‘panel’ is unnecessary.
 
layout: ‘fit’,
items: [{
    xtype : 'grid',
    title: ‘My Cool Grid’,
    store : 'MyStore',
    columns : [{...}]
}]
 
Example 1B. GOOD: The grid is already a panel so just use any panel properties directly on the grid.

2. Memory leaks caused by failure to cleanup unused components.

Many developers wonder why their apps get slower and slower the longer they are used. Failure to cleanup unused components as a user navigates throughout an app is one of the biggest reasons. In example 2A below, each time the user right-clicks on a grid row, a new context menu is created. If the user keeps this app open and right-clicks the row hundreds of times, they will wind up with hundreds of context menus that will never be destroyed. To the developer and user, the app “looks” visually correct because only the last context menu created is seen on the page. The rest are hidden away. As new menus are created without the old ones being cleaned up, the memory utilization for the app will keep increasing. This will eventually result in slower operation or a browser crash.
Example 2B is better because the context menu is created once when the grid is initialized and is simply reused each time the user right-clicks a row. However, if the grid is destroyed, the context menu will still exist even though it is no longer needed. The best scenario is example 2C where the context menu is destroyed when the grid is destroyed.
 
Ext.define('MyApp.view.MyGrid',{
    extend : 'Ext.grid.Panel',
    columns : [{...}],
    store: ‘MyStore’,
    initComponent : function(){
        this.callParent(arguments);
        this.on({
            scope : this,
            itemcontextmenu : this.onItemContextMenu
        });
    },
 
    onItemContextMenu : function(view,rec,item,index,event){
        event.stopEvent();
        Ext.create('Ext.menu.Menu',{
            items : [{
                text : 'Do Something'
            }]
        }).showAt(event.getXY());
 
    }
});
 
Example 2A. BAD: A menu will be created on every right-click and won’t ever be destroyed.
 
Ext.define('MyApp.view.MyGrid',{
    extend : 'Ext.grid.Panel',
    store : 'MyStore',
    columns : [{...}],
    initComponent : function(){
        this.menu = this.buildMenu();
        this.callParent(arguments);
        this.on({
            scope : this,
            itemcontextmenu : this.onItemContextMenu
        });
    },
 
    buildMenu : function(){
        return Ext.create('Ext.menu.Menu',{
            items : [{
                text : 'Do Something'
            }]
        });
    },
 
    onItemContextMenu : function(view,rec,item,index,event){
        event.stopEvent();
        this.menu.showAt(event.getXY());
    }
});
 
Example 2B. BETTER: Menu will be created when the grid is created and be reused each time.
 
Ext.define('MyApp.view.MyGrid',{
    extend : 'Ext.grid.Panel',
    store : 'MyStore',
    columns : [{...}],
    initComponent : function(){
        this.menu = this.buildMenu();
        this.callParent(arguments);
        this.on({
            scope : this,
            itemcontextmenu : this.onItemContextMenu
        });
    },
 
    buildMenu : function(){
        return Ext.create('Ext.menu.Menu',{
            items : [{
                text : 'Do Something'
            }]
        });
    },
 
    onDestroy : function(){
        this.menu.destroy();
        this.callParent(arguments);
    },
 
    onItemContextMenu : function(view,rec,item,index,event){
        event.stopEvent();
        this.menu.showAt(event.getXY());
    }
});
 
Example 2C. BEST: When the grid is destroyed, the context menu is also destroyed.

3. Monster controllers

It’s amazing how many times we see apps that have one huge controller with thousands of lines of code. We tend to favor breaking up our controllers by app function. For example, an order processing app might have individual controllers for line items, shipments, customer lookup, etc. It makes navigating and maintaining the code much easier.
Some developers like to break out controllers by view. For example, if an application had a grid and a form, there would be a controller to manage the grid and a controller to manage the form. There is no one “right” way to separate controller logic as long as you are consistent. Just remember, controllers can communicate with other controllers. In example 3A, you can see how to retrieve a reference to another controller and call one of its methods.
 
this.getController('SomeOtherController').runSomeFunction(myParm);
 
Example 3A. Get a reference to another controller and call a method.
Alternately you could fire an application level event that any controller can listen for. In examples 3B and 3C, you can see how one controller can fire an app-level event and another controller can listen for it.
 
MyApp.getApplication().fireEvent('myevent');
 
Example 3B. Fire an app-level event.
 
MyApp.getApplication().on({
    myevent : doSomething
});
 
Example 3C. Another controller listens for the app-level event.
Note: Beginning with Ext JS 4.2, it gets even easier to use multiple controllers -- they can fire events that other controllers can listen for directly.

4. Poor folder structure for source code

This doesn’t affect performance or operation, but it makes it difficult to follow the structure of your app. As your app grows, finding source code and adding features and functionality will be much easier if you organize your source code. We have seen that many developers will put all views (even for a large app) in one folder as shown in example 4A. We recommend adding organization to the views by logical function as shown in example 4B.
top 10 ext JS Practices Example 4A. BAD: All views are at one level.
top 10 ext JS Practices Example 4B. GOOD: Views are organized by logical function.

5. Use of global variables

Even though it’s widely known that global variables are bad, we have still see them used in some of the apps that we have recently reviewed. Apps that use global variables can have significant problems with name collisions and can be hard to debug. Instead of using global variables, we will hold “properties” in a class and then reference those properties with getters and setters.
For example, suppose your application needed to remember the last selected customer. You might be tempted to define a variable in your app as shown in example 5A. It’s easy and the value is conveniently available to all parts of your app.
 
myLastCustomer = 123456;
 
Example 5A. BAD: Global variable created to store last customer number.
Instead, it’s a better practice to create a class that holds properties intended to be used “globally.” In this case, we will create a file called Runtime.js to hold runtime properties intended to change as the app is used. Example 5B shows the location for Runtime.js in our source code structure.
top 10 ext JS Practices Example 5B. Location of the Runtime.js file.
Example 5C shows the contents of Runtime.js and example 5D shows how to “require” it in your app.js. You can then “set” and “get” your properties as shown in 5E and 5F from anywhere in the app.
 
Ext.define(‘MyApp.config.Runtime,{
    singleton : true,
    config : {
        myLastCustomer : 0   // initialize to 0
    },
    constructor : function(config){
        this.initConfig(config);
    }
});
 
Example 5C. Sample Runtime.js file to hold global properties for an app.
 
Ext.application({
    name : ‘MyApp’,
    requires : [‘MyApp.config.Runtime],
   ...
});
 
Example 5D. Require the Runtime class in your app.js file.
 
MyApp.config.setMyLastCustomer(12345);
 
Example 5E. How to set the last customer.
 
MyApp.config.getMyLastCustomer();
 
Example 5F. How to get the last customer.

6. Use of “id”

We don’t recommend the use of id’s on components because each id must be unique. It’s too easy to accidentally use the same id more than once, which will cause duplicate DOM id’s (name collisions). Instead, let the framework handle the generation of id’s for you. With Ext JS ComponentQuery, there is no reason to ever have to specify an id on an Ext JS component. Example 6A shows two code segments of an app where there are two different save buttons created, both of which were identified with an id of ‘savebutton’, causing a name collision. Although obvious in the code below, it can be hard to identify name collisions in a large application.
 
// here we define the first save button
xtype : 'toolbar',
items : [{
    text : ‘Save Picture’,
    id : 'savebutton'
}]
 
// somewhere else in the code we have another component with an id of ‘savebutton’
xtype : 'toolbar',
items : [{
    text : ‘Save Order’,
    id : 'savebutton'
}]
 
Example 6A. BAD: Assigning a duplicate ‘id’ to a component will cause a name collision.
Instead, if you want to manually identify each component you can simply replace the ‘id’ with ‘itemId’ as shown in example 6B. This resolves the name conflict, and we can can still get a reference to the component via itemId. There are many ways to retrieve a reference to a component via itemId. A few methods are shown in example 6C.
 
xtype : 'toolbar',
itemId : ‘picturetoolbar’,
items : [{
    text : 'Save Picture',
    itemId : 'savebutton'
}]
 
// somewhere else in the code we have another component with an itemId of ‘savebutton’
xtype : 'toolbar',
itemId: ‘ordertoolbar’,
items : [{
    text : ‘Save Order’,
    itemId: ‘savebutton’
}]
 
Example 6B. GOOD: Create components with an ‘itemId’.
 
var pictureSaveButton = Ext.ComponentQuery.query('#picturetoolbar > #savebutton')[0];
 
var orderSaveButton = Ext.ComponentQuery.query('#ordertoolbar > #savebutton')[0]; 
 
// assuming we have a reference to the “picturetoolbar” as picToolbar
picToolbar.down(‘#savebutton’);
 
Example 6C. GOOD: Referencing components by ‘itemId’.

7. Unreliable referencing of components

We sometimes see code that relies on component positioning in order to get a reference. This should be avoided as the code can easily be broken if any items are added, removed or nested within a different component. Example 7A shows a couple common cases.
 
var mySaveButton = myToolbar.items.getAt(2);
 
var myWindow = myToolbar.ownerCt;
 
Example 7A. BAD: Avoid retrieving component references based on component positioning.
Instead, use ComponentQuery, or the component “up” or “down” methods, to retrieve references as shown in example 7B. With this technique the code will be less likely to break if the structure or ordering of components is subsequently changed.
 
var mySaveButton = myToolbar.down(‘#savebutton’);    // searching against itemId
 
var myWindow = myToolbar.up(‘window’);
 
Example 7B. GOOD: Use ComponentQuery to retrieve relative references.

8. Failing to follow upper/lowercase naming conventions

There are certain upper/lowercase standards that Sencha follows when naming components, properties, xtypes, etc. To avoid confusion and to keep your code clean, you should follow the same standards. Example 8A shows several incorrect scenarios. Example 8B shows the same scenarios with the correct upper/lowercase naming conventions.
 
Ext.define(‘MyApp.view.customerlist,{          // should be capitalized and then camelCase
    extend : ‘Ext.grid.Panel,
    alias : ‘widget.Customerlist,                       // should be lowercase             
    MyCustomConfig : ‘xyz’,                            // should be camelCase
    initComponent : function(){
        Ext.apply(this,{
            store : ‘Customers’,
            ….
        });
        this.callParent(arguments);
    }
});
 
Example 8A. BAD: Areas in bold type have incorrect upper/lowercase naming.
 
Ext.define(‘MyApp.view.CustomerList,{      
    extend : ‘Ext.grid.Panel,
    alias : ‘widget.customerlist,      
    myCustomConfig : ‘xyz’,            
    initComponent : function(){
        Ext.apply(this,{
            store : ‘Customers’,
            ….
        });
        this.callParent(arguments);
    }
});
 
Example 8B. GOOD: Areas in bold follow all of the correct upper/lowercase rules.
Additionally, if you are firing any custom events, the name of the event should be all lowercase. Of course, everything will still work if you don’t follow these conventions, but why stray outside of the standards and write less clean code?

9. Constraining a component to a parent component’s layout

In example 9A, the panel will always have the ‘region:center’ property and thus would not work if you ever wanted to reuse the component and put it in a “west” region, for example.
 
Ext.define('MyApp.view.MyGrid',{
    extend : 'Ext.grid.Panel',
    initComponent : function(){
        Ext.apply(this,{
            store : ‘MyStore’,
            region : 'center',
            ......
        });
        this.callParent(arguments);
    }
});
 
Example 9A. BAD: The ‘center’ region should not be specified here.
Instead, specify the layout configuration when creating the component as shown in example 9B. This way, you can reuse the component anywhere you like and not be constrained by the layout configuration.
 
Ext.define('MyApp.view.MyGrid',{
    extend : 'Ext.grid.Panel',
    initComponent : function(){
        Ext.apply(this,{
            store : ‘MyStore’,
            ......
        });
    }
});
 
// specify the region when the component is created...
Ext.create('MyApp.view.MyGrid',{
    region : 'center' 
});
 
Example 9B. GOOD: Specify the region when creating the component.
As shown in example 9C, you can also provide a default region on the component that could be overridden if necessary.
 
Ext.define('MyApp.view.MyGrid',{
    extend : 'Ext.grid.Panel',
    region : 'center', // default region
    initComponent : function(){
        Ext.apply(this,{
            store : ‘MyStore’,
            ......
        });
    }
});
 
Ext.create(‘MyApp.view.MyGrid,{
    region : ‘north’, // overridden region
    height : 400
});
 
Example 9C. Also GOOD: Specify a default region and override if necessary.

10. Making your code more complicated than necessary

There are many times we see code that is more complicated than necessary. This is usually a result of not being entirely familiar with each component’s available methods. One of the most common cases we see is code that loads each form field from a data record individually. Example 10A shows an example of this.
 
//  suppose the following fields exist within a form
items : [{
    fieldLabel : ‘User’,
    itemId : ‘username’
},{
    fieldLabel : ‘Email’,
    itemId : ‘email’
},{
    fieldLabel :Home Address’,
    itemId : ‘address’
}];
 
// you could load the values from a record into each form field individually
myForm.down(‘#username’).setValue(record.get(‘UserName’));
myForm.down(‘#email’).setValue(record.get(‘Email’));
myForm.down(‘#address’).setValue(record.get(‘Address’));
 
Example 10A. BAD: Loading form fields from a record individually.
Instead of loading each value individually, use the loadRecord method to load all fields from the record into the proper form fields with one line of code. The key is to make sure the “name” property of the form field matches the field name of the record as shown in example 10B.
 
items : [{
    fieldLabel : ‘User’,
    name : ‘UserName’
},{
    fieldLabel : ‘Email’,
    name : ‘Email’
},{
    fieldLabel :Home Address’,
    name : ‘Address’
}];
 
myForm.loadRecord(record);
 
Example 10B. GOOD: Use loadRecord to load all form fields with one line of code.
  • ext-all.js: minified, no docs/comments
  • ext-all-debug.js: non-minified, no docs/comments
  • ext-all-debug-w-comments.js: non-minified, with docs/comments
  • ext-all-dev.js: non-minified, with docs/comments, with console warnings, e.g. if you're using deprecated functions/configs or there are configuration problems. The additional console output in ext-all-dev.js can be really helpful, so I'd recommend it for development.
  • ext-all-debug.js: (or ext-all-debug-w-comments.js) is functionally the same as ext-all.js, allows better debugging since it's not minified. I'd recommend it for testing purposes.
  • ext-all.js: obviously is what you want to use in production, since the file is much smaller than the other files.
Ext JS 5 will introduce a bunch of new features, including:
  • Tablet support
  • Two-way data binding
  • New MVVM Application Architecture
  • Widgets and the Widget Column
  • Crisp Theme
  • Routing
  • and much more!

5 comments: