Stand With Ukraine. Stop Putin. Stop War.

For whatever reason, sometimes it's seems complicated to get a working tabbed window that is also a form using ExtJS/modExt. And then when you do, the height of the shadow doesn't resize when the window does when you change tabs. Here's one way to pull all of that off and how I got this working in the bdListings component.

All of the below assumes you know the basics of ExtJS, and that all you need is a gentle push in the right direction to get this working in your own custom manager pages in MODX. If you're not yet at that level, I suggest reading up on stuff.

By default, the MODx.window includes a FormPanel, meaning that it is expecting fields. So while it may sounds more logical to actually use an items or components config option, the window will be expecting fields.

So let's give that to the window, shall we? I've included some default options you probably want here as well.

myComponent.window.Listing = function(config) {
    config = config || {};
    Ext.applyIf(config,{
        title: _('mycomponent.listing'),
        url: bdListings.config.connector_url,
        closeAction: 'close',
        autoHeight: true,
        baseParams: {
            action: 'mgr/listings/save'
        },
        fields: [{
            xtype: 'modx-tabs',
            autoHeight: true,
            deferredRender: false,
            forceLayout: true,
            width: '98%',
            bodyStyle: 'padding: 10px 10px 10px 10px;',
            border: true,
            defaults: {
                border: false,
                autoHeight: true,
                bodyStyle: 'padding: 5px 8px 5px 5px;',
                layout: 'form',
                deferredRender: false,
                forceLayout: true
            },

So what you're seeing there is a few things.

  1. We're passing a title, connector URL and action, closeAction (which in this case destroys the window on close), and the arguement to use autoheight. Note that autoHeight only seems to affect the first load.
  2. We add a field with xtype modx-tabs, which is how we would normally be using the tabs in MODX anyway.
  3. The modx-tabs is given some config options (not all would be neccessary):
    • Use autoHeight
    • Do not defer (=delay) rendering until we open the tab, and force a layout. These options make sure the markup is always avialable, which is essential when you are going to be posting the form and using validation.
    • Give it a 98% width and some padding, as well as a border for looks.
    • Tell the underlying items (the individual tabs) to use the following defaults:
      • Use no border, automatic height and some padding for looks.
      • Use the "form" type layout, this is crucial to display labels and fields correctly.
      • Do not defer rendering & force layout.

Now, not all of those options should be neccessary but I haven't had the motivation to figure out which ones or what combination get the right effect. Maybe someone can add to that in the comments? Thanks!

Now that we've got the basic tabpanel set up, we should add the tabs and some forms. Here's an example of that (which starts off where the last code block ended):

 items: [{
                title: _('mycomponent.listing.details'),
                items: [{
                    name: 'id',
                    xtype: 'statictextfield',
                    fieldLabel: _('id'),
                    width: '95%',
                    submitValue: true
                },{
                    name: 'title',
                    xtype: 'textfield',
                    fieldLabel: _('mycomponent.title')+'*',
                    allowBlank: false,
                    width: '95%'
                }]

So we're using the known items object here, and we also give this individual tab a title from our Lexicon file. Then we add two items to this tab, namely an "id" statictextfield and a "title" textfield. The statictextfield can be used to just display text that cannot be modified by the average user (of course us web devs could just use Firebug to go in and change the field to a textfield should we want to :) ), and we also tell that to submit the value in it to make sure our processor has access to the ID when saving.

We can repeat the above block for more tabs, more items, etc etc. Just finish off the rest of the configuration like usual, making sure all brackets are closed properly. I personally use PhpStorm and that's pretty awesome at figuring out if something is missing or wrong.

Making sure the window resizes when changing tabs

Now that we've got working tabs in our window you will notice that if they are different in height, you will see the background shade doesn't resize along. For this we can use the syncSize function on the window. Whenever you change a tab, the "tabchange" event fires on the tabpanel which is what we'll need.

Add this code to the tabpanel configuration, ie the modx-tabs xtype we loaded.

          listeners: {
                'tabchange': function() {
                    this.syncSize();
                },
                scope: this
            }

What this does is that it listens for the tabchange event, and if that happens we fire the syncSize function. But as that is a function on the window object, and not the tab object, we will need to specify the scope:this to the listener option which makes sure that if we reference "this" it's actually the window object.

You can find a complete example with all these different parts in the bdListings repository.

Jeroen Kenters

Thanks! Saved me a lot of time :-)

lossendae

Good article!
You can also use anchor: '100%' instead of width: '98%' so that all fields will never bleed over the available place while keeping the padding on each side equal (with width, the larger the screen, the larger the padding on the right).

Mark Hamstra

Thanks Stephane!

I've been using anchor: "1" on buttons and comboboxes, however that seemed to overflow (and get cut off) when used on reguler text/number fields. However, anchor: "100%" seems to work great!

Thanks for that great tip, now to update my project again.... :)

Ellis Grouse

Awesome - just what I was looking for.
Was trying to figure out how I could do nicer layouts for form windows the last few weeks!

javadecaf

Thanks, Mark - this helped get me started in the right direction. For anyone else that might run into this problem, I found that combo boxes don't render properly except on the active tab. The solution, (which I found here: http://www.sencha.com/forum/showthread.php?60396-Strange-combobox-width-problem) was to add hideMode: 'offsets' to the 'defaults' property.

Comments are closed :(

While I would prefer to keep comments open indefinitely, the amount of spam that old articles attract is becoming a strain to keep up with and I can't always answer questions about ancient blog postings. If you have valuable feedback or important questions, please feel free to get in touch.