Friday, April 25, 2014

Destroy of Dynamically created stores

         Often a need arises when we create stores dynamically and not through the general MVC structus, Since those stores are global (app scope). We may want to create stores dynamically for select fields per screen,lists,etc.

         While working on one such scenario, I had a doubt on the destruction of these stores.
I installed the chrome plugin from Sencha: https://chrome.google.com/webstore/detail/app-inspector-for-sencha/pbeapidedgdpniokbedbfbaacglkceae?hl=en

What you can do is open a Screen using dynamic stores, Go to the stores tab and you will notice all the stores listed in the App.
Now, Navigate to some other Screen, and come back to the screen you visited, The store count keeps on increasing and the previous stores are never destroyed.

I went through the Grid source Code: http://docs.sencha.com/touch/2.3.1/source/Grid.html#Ext-grid-infinite-Grid. You will notice that Sencha has explicitly set the autoDestroy to true.

Hence, also checked the store source code: http://docs.sencha.com/touch/2.3.1/source/Store.html#Ext-data-Store and noticed that for Stores the autoDestroy config is set to false by default, as opposite to any components where its set to true by default.

For stores that are declared globally, under the stores namespace, they are not destroyed throughout the app. We are ensuring that we clean records in them. However, for dynamically created stores, we will need to set the autoDestroy to true or destroy them explicitly. If this is not done the stores along with the records keep on increasing as the screens are visited.

This will certainly give some improvement in terms of memory!. 
Feel free to discuss any views on this :).

Using Sencha Cmd for ExtJs

                 Sencha Cmd is a cross-platform command line tool that provides many automated tasks around the full life-cycle of your applications from generating a new project to deploying an application to production.
—    More info. @ http://docs.sencha.com/extjs/4.2.0/#!/guide/command

Sencha Cmd Installation:
Sencha Cmd is designed for Sencha Ext JS version 4.1.1a or higher and Sencha Touch version 2.1 or higher.
Steps to install Sencha Cmd:
1. Download and install a Java Run-time Environment or JRE. The JRE version must be at least JRE 6.
2. To build themes using Sass on Windows, download and install Ruby
3. Download and install Sencha Cmd.

Using Sencha Cmd:
Creating/generating the  application structure.
  • The following command is used to generate the app. Structure:
        sencha -sdk /path/to/SDK generate app MyApp /path/to/MyApp
  • You can refer the sencha  guide, for the exact structure generated using Sencha  Cmd.
  • All that is required to build your application is to run the following command:
         sencha app build

Custom Builds:
The following steps need to be followed for custom builds:
  • Add the following code in the html file:

    <!--<x-compile>-->
    <!--<x-bootstrap>-->
    <script src="../extjs/ext-dev.js"></script>
    <!--</x-bootstrap>-->
    <script src="app.js"></script>
    <!--</x-compile>-->
  • Create an output file with .html or .js extension. Suppose we create index.js
  • Use the following command to compile/build the all-classes file:
    sencha  compile  -classpath=app.js,../../extjs/src,(other custom utils/components) page -in=../app.html -out=index.js
  • The above command will generate an all-classes.js file, which has to be included in the app.html file. While including the generated all-classes file, remove the above added code and the includes for extjs library (ext-all.js) and app.js
  • Also, to generate the app-classes file as a compressed file using YUI, use the following command:
    sencha  compile  -classpath=app.js,../../extjs/src,(other custom utils/components) page -yui -in=../app.html -out=index.js
  • The ux components can be added to the ux folder in the source and would be referred from there. Incase you define custom components and do not want to add them as ux, you can add them to the classpath




Friday, February 14, 2014

Ext.override in EXTJs 4.x

Many times we override the behavior of the base EXTjs classes. With the earlier version of EXTjs, we did that using Ext.override. ExtJs 4 onwards the preferred way to achieve the same is using the Ext.define.

Ex: Ext.define('Override.view.Table',{
override:'Ext.view.Table',
.
.
.
});

Thursday, January 16, 2014

Enabling HTML5 Cacheing on Iphone or Ipad

HTML 5 Cache is a common feature, required by every app now a days. Application Cache is different from a Browser Cache. Found a very good blog explaining HTML 5 Cache: http://gregsramblings.com/2012/05/28/html5-application-cache-how-to/

Handle Header Tap of a Grouped List

There was a Menu that I was displaying, which had various options. The Menu had sub-items which were grouped. I had offcourse used the grouped list for the Menu.

However, also, the group header tap had to be handled, which had some view to be shown.
The Sencha touch list has an itemtap event that can be used to handle taps on each item, but there is no event that will handle the tap on Group Header.

I used the following to achieve it:
{
  xtype:'list',
  store:'SomeStore',
  grouped:true,
  listeners:{
   element:'element',
   delegate:'div.x-list-header',
   tap:function(e){
    var header = e.getTarget('div.x-list-header',3,true),
    scroller = e.getTarget('div.x-scroll-scroller',4,true),
    headers = scroller.query('div.x-list-header');
    index = header ? headers.indexOf(header.dom):false,
    store = this.getStore(),
    groups = store.getGroups(),
    group = groups[index];
    this.fireEvent('headerTap',group,e);
   }
 }
}

Now, you can add a listener on the list in the controller to listen to the headerTap event.

Combining UNION ALL to get a single record

During one of my projects, I landed up using a UNION ALL to get the resultset. However, UNION ALL gave 2 records of the 2 separate queries. We wanted to combine these 2 records of union all into one single record.

This is how I could achieve it:
select
    sub.gn as groupname,
    sum(sub.nj) as AJobs, sum(sun.nc) as ACnt,
    sum(sub.sj) as BJobs, sum(sub.sc) as BCnt
  from (
      select
          groupname as gn,
          sum(jobs) as nj, sum(cnt) as nc,
          0 as sj, 0 as sc
        from tbl
          where type= 'A'
          group by groupname
        union all select
            groupname as gn,
            0 as nj, 0 as nc,
            sum(jobs) as sj, sum(cnt) as sc
          from tbl
          where subsys = 'B'
          group by groupname
    ) as sub
    group by sub.gn
    order by 1

where tbl is a table with fields type,groupname,jobs and count.
The query basically gets the total jobs and count for type = A,B for all groups.

Wednesday, September 18, 2013

CORS throwing error when withCredentials is true

Cross-Origin Resource Shari (CORS) is a W3C spec that allows cross-domain communication from the browser. Almost most of the mobile app's you develop these days need to use CORS for cross-domain access of the web-services. You can find more information on CORS on : http://www.html5rocks.com/en/tutorials/cors/ .

 I had used CORS in many of my projects. To use CORS in EXTJS/Sencha Touch, you can create the request object as:
 var request = {
                                url: uri,
                                timeout: 120000,
                                useDefaultXhrHeader:false,
                                method: 'GET',
                                withCredentials:true,
                                scope:this
}             
Ext.Ajax.request(request);

While Using CORS and web-services together many a times you need to pass credentials or use the withCredentials attribute/config as indicated above.
But, It gave me an error indicating: "Cannot use wildcard in Access-Control-Allow-Origin when credentials flag is true." 

Basically, when you are using Cross Domain along with withCredentials set to "true", the server has to respond with:
Access-Control-Allow-Origin: (the origin url) and not with
Access-Control-Allow-Origin:*
WildCards are not allowed in this case.
So this is what I used on the server side:
headers['Access-Control-Allow-Origin'] = this.req.headers.origin;
Hope this helps!!!...