Dynamic Toolbar Menus with ExtJS + PHP

In Ext JS 4 there’s some handy things that come bundled with it (there’s lots of stuff actually – it’s a pretty large library). Recently, though, I needed to pull in navigation information from a remote source (JSON output from a PHP script). Thankfully, Ext still made this pretty easy with its Toolbar and Menu components with their listeners. Here’s my example code:

[javascript]
Ext.create(‘Ext.toolbar.Toolbar’, {
floating: false,
id: ‘menuToolbar’,
cls: ‘appMenu’,
height: 30,
items: [], // dynamically built below
listeners: {
beforerender: function() {
var navStore = Ext.create(‘Ext.data.Store’, {
fields: [‘text’],
proxy: {
type: ‘ajax’,
url: ‘/path/to/navigation-output’,
reader: {
type: ‘json’,
root: ‘navigation’
}
},
autoLoad: true,
listeners: {
load: function(store,records,success,operation,opts) {

var toolbar = Ext.getCmp(‘menuToolbar’);

// First the top level items
store.each(function(record) {

var menu = Ext.create(‘Ext.menu.Menu’);
Ext.each(record.raw.menu, function(item){
menu.add({
text: item.text
})
})

toolbar.add({
xtype: ‘button’,
text: record.data.text,
menu: menu
});
});
}
}
});
}
}
});
[/javascript]

Then the PHP to make the output is pretty easy (slightly simplified here):

[php]
<?php
echo json_encode(
‘navigation’ => array(
‘text’ => ‘Option #1′,
‘menu’ => array(
array(‘text’ => ‘Foo’),
array(‘text’ => ‘Bar’),
array(‘text’ => ‘Baz’)
)
)
);
?>
[/php]

Now – a little explaination of what we’re doing here:

  1. In Ext, we create a generic Toolbar object – this is what’s going to contain the “buttons” that act as the top level menu.
  2. There’s a few config options (like an ID, height and a custom class to apply) but the key is in the “listeners” section. This is where Ext looks to for events on the objects. In our case, we’re telling it to, on the “beforerender” event, call this given inline method. This method then makes our store.
  3. For those not familiar with the ideas of “stores”, think of them as Javascript-based database tables (kinda). They pull in data from some source or can be manually populated in memory to prevent you from having to go back and fetch the data every time you need it. in our case, we just make a basic one (Ext.data.Store) that is set up with a proxy to pull from the JSON source (our /path/to/navigation-output). With the “autoLoad” property set to “true” it automatically pulls in the JSON as soon as it’s created.
  4. You’ll see that we’ve, once again, tapped into the “listeners”, this time for the store. Our “load” listener fires when the store data is completely loaded. In here is where we’re going to add our elements into the Toolbar.
  5. As one of the options, we get the current store back and we use it to loop through and get each of the records. Each of these top level records is going to be one of our Toolbar buttons, each with its own menu. You can see as we loop through them, we create an “Ext.menu.Menu” object adding the “text” value to it. This menu is then appended to the button via the “menu” property on the button. The “add” is called again on the button config and it’s dropped into the Toolbar.

The fun thing about this is that it makes a reusable component that you can use across products/sites without having to hard-code the navigation options into the actual code. There’s probably a simpler way to do this, but this one seemed to make the most sense to me.

4 comments

  1. Hi,

    Thanks for the code. Works like a charm. But I want to keep sub items in sub menus. Your example have only two level Menu and Sub-menu. What if I have three levels that is having items in sub-menus. Can you please provide me the code.

    Also, how to add the links to that menus.

    Thanks in advance,
    Sateesh B.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>