views:

579

answers:

2

I have a custom component that extends a panel. The panel has a top tool bar with a basic config. I want to be able to add items to the panel dynamically after it has been created.

Those items should always come at the end of the main set of menu items and before the filler that pushes the logout button to the far right, so I wrote the insertMenuItem function to grab the position of the "shunt" (the tbfill) item and insert the new toolbar item at this location. If it doesn't find the "shunt", because its been overridden, it just adds to the end of the toolbar.

This seems to work just great. If I look at the "live" contentPanel I can see the inserted menu item. The problem come with getting it to display. Now I suspect that this is a scoping issue, I'm just not sure what, where, when, how.... :|

I've tried this.doLayout(), topToolbar.doLayout() in the function I've got a doLayout() on the contentPanel object after calling my function, but none of them seem to help.

HELP! ;-D

Below is my extended Panel class. Thanks in advance for your help

Stephen


SOM.ux.contentPanel = Ext.extend(Ext.Panel, {
     autoScroll:true
    ,initComponent:function() {
        var config = {
             plugins:['dispatcher']
            ,contentEl : Ext.get('som-body')
            ,tbar:{
                     itemId:'contenttoolbar'
                    ,items:[
                {
                    xtype : 'button',
                    text: 'Dashboard',
                    handler: function(){
                        document.location.href = '/'
                    }
                },{itemId:'shunt',xtype: 'tbfill'},{
                    xtype : 'button',
                    text: 'Logout',
                    handler: function(){
                        document.location.href = '/admin.login.doLogout'
                    }
                },{
                        xtype : 'tbbutton',
                        text: 'Message',
                        scope: this,
                        handler: function(){
                            this.publish('SOM.ux.Dashboard',{action:'doHelloWorld',params:{name:'Stephen'}});
                        }
                    }
                ]
            }

        }; // end of config
        Ext.apply(this, Ext.apply(this.initialConfig, config));
        SOM.ux.contentPanel.superclass.initComponent.apply(this, arguments);
    }
    ,afterRender: function(){
        this.subscribe('SOM.ux.Toolbar');
        SOM.ux.contentPanel.superclass.afterRender.call(this);
    }
    ,onDispatchMessage: function(subject,message) {
        if (message.action) {
            this[message.action].call(this,message.params);
        }       
        console.log('contentpanel doDispatch',subject,message);
    }
    ,insertMenuItem: function(itemObj){
        var topToolbar = this.getTopToolbar();
        var aItems = topToolbar.items;
        var insertPos = aItems.indexOfKey('shunt');
        if (insertPos) {
            console.log('using insert');
            topToolbar.insert(insertPos,itemObj);
        } else {
            console.log('using add');
            topToolbar.add(itemObj);
        }
        this.getTopToolbar().doLayout();
    }

+1  A: 

Make sure you are calling insertMenuItem after the toolbar has rendered. Is itemObj (the param) an Ext.Toolbar.Item config?

Jonathan Julian
Embarrassingly, it wasn't a toolbar item. It was just the menu object itself. With all the new things I've learn this last week and all the change I've made I'd just completely forgot to put the menu into a toolbar item config and couldn't see this without you prompting me to check. Thanks Jonathan.
Stephen Moretti
I think you can add a full object *or* a config. It's often preferable to use configs when defining components, as the object isn't created until it's needed (xtype). And the code feels alot cleaner: it's a *definition*, not an *instance*.
Jonathan Julian
+1  A: 

The following works:

var tb = new Ext.Toolbar({ items : [{text : 'wtf'}] });

new Ext.Window({ width : 300, height : 100, tbar : tb }).show();

(function() { tb.add({text:'new btn'}); tb.doLayout() }).defer(1500);

To add to jonathan's comment, only call doLayout after it's rendered.

Jay Garcia
This is a great way to test one's sanity...write the least amount of code to make it work, then compare that to the broken code.
Jonathan Julian