Thursday, March 1, 2012

Sencha touch 2 : Dynamically set title of Navigation bar

Hello,

If you are using Sencha touch 2 beta 3, you might have encounter this issue. If you have a view that you pushing in navigation view you can set title there. This title will be used as a title of navigation bar when this view is activated.  See the following code.


config: {
        autoDestroy: false,
        title: 'Bill'
}

What if you have requirement of setting this dynamically. For example you have a list from which you selected a category.

-Category 1
-Category 2
-Category 3

Based on selected record you will load sub category in next view and you want to display Category 1 as a title in next screen. To load next view you will create it first and push it.


if (!this.menuSubCategory) {
                this. menuSubCategory = Ext.create('Application.view.SubCategory');
}
this.getMain().push(this. menuSubCategory);

Here you can set title if you want when you are first creating item. After that you can set it as you already have view. Either you can destroy view every time and create new one else you apply following trick.

This is how next view is loaded. Now if you have set title in config of above view. It will be applied by default. So to dynamically set it you need to do some tweak. First you need to override a base function. See the following code.


Ext.override(Ext.navigation.Bar, {
    getNavigationBarProxyProperties: function () {
        return {
            title: {
                left: this.proxy.titleComponent.renderElement.getLeft()
            },
            backButton: {
                left: this.proxy.backButton.renderElement.getLeft(),
                width: this.proxy.backButton.renderElement.getWidth()
            }
        };
    }
});



Create an overrides file and add it after sencha touch js file. This is necessary else title width will be less compared to title

Now add the following code after you pushed your view to navigation view.

this.getMain().query('#navBar')[0].titleComponent.setWidth(100);
this.getMain().query('#navBar')[0].titleComponent.setTitle('categoryName');  

That's it and you have dynamic title in navigation view. Please note this trick you need to apply if you are using Sencha touch 2 beta 3 version.

Friday, February 24, 2012

Sencha touch Error - TypeError: 'undefined' is not an object (evaluating 'o.id')

Hello,

If you are working with Sencha touch 2 or earlier versions you might had below mentioned error while working with list or selectfield

TypeError: 'undefined' is not an object (evaluating 'o.id')


Normally this error displayed when you are trying to select some old records in list or selectefield. For example you have a list on the form or a panel to select some records which you are saving in database and in case of edit you want to show last selected records. So we normally add code to select records on refresh. Something like below.


myList.on('refresh', function () {
                for (var i = 0; i < userSelectedRecords.getCount(); i++) {
                    var record =  userSelectedRecords .getAt(i);
                        var recordIndex =  myList .store.find('idField',  record.get('idField'));
                         myList .getSelectionModel().select(recordIndex, true, false);
                }
        },
        this,
        { single: true }
);


In above code last selected records are stored in userSelectedRecords and we are fetching records from it and selecting respective record in list. Now above refresh method fired two times. First when the list container like panel is rendered and second time when list store loaded with data. And as we all know sencha touch store load is asyc method so if you simply adding following line just above the refresh event handler this error is likely to come. Because by the time refresh event fired store load is still going on. Particularly this happens if you are loading store using Ajax proxy. Some time this error breaks your layout and freezes the panel. You don't have other option than reloading the app. To prevent this you can simply add store count check in refresh so first time when panel is rendered if store load it not complete, it will not try to select data. It will select it when store load completes.

Following is the code.


myList.on('refresh', function () {
               if(myList.store.getCount()>0)
                       for (var i = 0; i < userSelectedRecords.getCount(); i++) {
                            var record =  userSelectedRecords .getAt(i);
                             var recordIndex =  myList .store.find('idField',  record.get('idField'));
                             myList .getSelectionModel().select(recordIndex, true, false);
                       }
                }
        },
        this,
        { single: true }
);

Please note above code will work for sencha touch 1.1 and earlier version. For later versions you can do that check in controllers action.

Hope this helps you.

Friday, February 10, 2012

Sencha touch 2.0 Panel Align Button Left and Right

Hello,

Recently I was working with Sencha touch 2.0 and I had a requirement to align buttons in panel. One button should be left side and other should be on right side. Something like image below.


This is easily possible if we use toolbar. check the following code.


{
   xtype: 'panel',
   dockedItems: [{
                             xtype: 'toolbar',
                             docked: 'bottom',
                             items: [{
                                           xtype: 'button',
                                           text: 'Multiple Choice',
                                           ui: 'confirm'
                                        }, {
                                           xtype:'spacer'
                                        }, {
                                           xtype: 'button',
                                           text: 'Sort and Match',
                                           ui: 'confirm'
                              }]
              }]
}

But what if you have to use panel. You can use hbox layout to align buttons horizontally but how can we have gap between them because spacer will not work in panel. You can use flex property here. Check the following code.


{
    xtype: 'panel',
    layout: 'hbox',
    title: 'Play Game',
    items: [{
                  xtype: 'button',
                  text: 'Multiple Choice',
                  ui: 'confirm',
                  flex: 0.3
                }, {
                  xtype:'panel',
                  flex: 0.4
                }, {
                  xtype: 'button',
                  text: 'Sort and Match',
                  ui: 'confirm',
                  flex: 0.3
        }]
}

It will give you following output.


That's it and you have desired output.