1. #1
    Sencha Premium Member
    Join Date
    Jun 2008
    Posts
    51
    Vote Rating
    1
    mbajema is on a distinguished road

      0  

    Default Ext.ux.layout.TableFormLayout

    Ext.ux.layout.TableFormLayout


    I've seen a number of posts by users wishing field labels rendered in the table layout (they do in the column layout for example). A common response is to wrap each field with a container/panel with the form layout. This does work, but requires a lot of nested containers.

    I created a very simple table-form layout which automatically wraps each item with an Ext.Panel with a form layout so that field labels are rendered as well (for some reason I couldn't get this to work with an Ext.Container):

    Source:
    Code:
    Ext.namespace('Ext.ux.layout');
    Ext.ux.layout.TableFormLayout = Ext.extend(Ext.layout.TableLayout,
    {
        renderAll : function(ct, target)
        {
            var items = ct.items.items;
            for (var i = 0, len = items.length; i < len; i++)
            {
                var c = items[0]; // use 0 index because the array shrinks by one after each call to renderItem()
                if (c && (!c.rendered || !this.isValidParent(c, target)))
                {
                    this.renderItem(c, i, target);
                }
            }
        },
    
        renderItem : function(c, position, target){
            if (c && !c.rendered)
            {
                var td = this.getNextCell(c);
                var p = new Ext.Panel(Ext.apply(this.container.formConfig,
                {
                    layout: 'form', // this is the tableform layout so force each cell panel to have a form layout
                    items: c,
                    renderTo: td
                }));
            }
        }
    });
    Ext.Container.LAYOUTS['tableform'] = Ext.ux.layout.TableFormLayout;
    Sample:
    Code:
    Ext.onReady(function()
    {
        Ext.QuickTips.init();
    
        var p = new Ext.Panel(
        {
            layout: 'tableform',
            title: 'Table-Form Layout',
            bodyStyle: 'padding:6px',
            renderTo: Ext.getBody(),
            layoutConfig: {columns:3},
            formConfig: // config options to be applied to each panel in each table cell
            {
                layoutConfig:
                {
                    labelSeparator: ''
                },
                bodyStyle: 'padding:0 3px',
                labelAlign: 'top',
                border: false
            },
            items:
            [
                {
                    xtype: 'textfield',
                    fieldLabel: 'Field 1',
                    name: 'Field1',
                    width: 115
                },
                {
                    xtype: 'textfield',
                    fieldLabel: 'Field 2',
                    name: 'Field2',
                    width: 115
                },
                {
                    xtype: 'textfield',
                    fieldLabel: 'Field 3',
                    name: 'Field3',
                    width: 115
                },
                {
                    xtype: 'textfield',
                    fieldLabel: 'Field 4',
                    name: 'Field4',
                    width: 115
                },
                {
                    colspan: 2,
                    xtype: 'textfield',
                    fieldLabel: 'Field 5',
                    name: 'Field5',
                    width: 236
                }
            ]
        });
    });
    Demo:
    http://www.innovativetechsolutions.n.../tableform.htm

  2. #2
    Ext JS Premium Member
    Join Date
    Mar 2007
    Location
    NL
    Posts
    608
    Vote Rating
    1
    mdissel is on a distinguished road

      0  

    Default


    Very nice! it fixes two "errors":
    - tab order
    - anchoring when using multiple columns (and col spanning)

  3. #3
    Ext JS Premium Member
    Join Date
    Mar 2007
    Location
    NL
    Posts
    608
    Vote Rating
    1
    mdissel is on a distinguished road

      0  

    Default


    One issue when using anchoring.. The size of the fields is not correct when i changed your sample using this config:

    Code:
            layoutConfig: {columns:3},
            formConfig: // config options to be applied to each panel in each table cell
            {
                layoutConfig:
                {
                    labelSeparator: '',
    				anchor: '88%'
    		},
    		defaults:{
    			msgTarget: 'side'
    		},
                bodyStyle: 'padding:0px 3px',
                labelAlign: 'top',
                border: false
            },

  4. #4
    Ext User
    Join Date
    Feb 2008
    Posts
    4
    Vote Rating
    0
    debarcar is on a distinguished road

      0  

    Default ok for ext 2.0 but failure in ext 2.1

    ok for ext 2.0 but failure in ext 2.1


    It is great extension!

    In my environment, it is ok for ext 2.0 library...but when I switch to 2.1 library, it show:

    A.container has no properties
    [IMG]chrome://firebug/content/blank.gif[/IMG]Ext.FormPanel=Ext.extend(Ext.Panel,{buttonAlign:"center",minButtonWidth:75,label...

    Could you please to tell me how to fix this?

  5. #5
    Sencha - Ext JS Dev Team Animal's Avatar
    Join Date
    Mar 2007
    Location
    Notts/Redwood City
    Posts
    30,506
    Vote Rating
    54
    Animal has a spectacular aura about Animal has a spectacular aura about Animal has a spectacular aura about

      0  

    Default


    Bit heavyweight to use a Panel as the inner Container. You don't need all the machinery of Panel, it's only a Container, and you can use the existing <td> as the element for it, so no need for any deep DOM nesting...:

    try this, and let us know how it goes:

    Code:
        renderItem : function(c, position, target) {
            if (c && !c.rendered) {
                var td = this.getNextCell(c)
                new Ext.Container(Ext.apply(this.container.formConfig,  {
                    el: td,
                    renderTo: td.parentNode,
                    layout: 'form', // this is the tableform layout so force each cell to have a form layout
                    items: c
                }));
            }
        }

  6. #6
    Sencha - Ext JS Dev Team Animal's Avatar
    Join Date
    Mar 2007
    Location
    Notts/Redwood City
    Posts
    30,506
    Vote Rating
    54
    Animal has a spectacular aura about Animal has a spectacular aura about Animal has a spectacular aura about

      0  

    Default


    OK, how about this version?

    Code:
    <html>
    <head>
        <title>Absolute Forms</title>
        <link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css"/>
    
        <!-- GC -->
        <!-- LIBS -->
        <script type="text/javascript" src="../../adapter/ext/ext-base.js"></script>
        <!-- ENDLIBS -->
    
        <script type="text/javascript" src="../../ext-all-debug.js"></script>
    
        <link rel="stylesheet" type="text/css" href="forms.css"/>
    
        <!-- Common Styles for the examples -->
        <link rel="stylesheet" type="text/css" href="../examples.css"/>
    </head>
    <script type="text/javascript">
    
    Ext.override(Ext.layout.FormLayout, {
    	fieldTpl: (function() {
    		var t = new Ext.Template(
                '<div class="x-form-item {5}" tabIndex="-1">',
                    '<label for="{0}" style="{2}" class="x-form-item-label">{1}{4}</label>',
                    '<div class="x-form-element" id="x-form-el-{0}" style="{3}">',
                    '</div><div class="{6}"></div>',
                '</div>'
            );
            t.disableFormats = true;
            return t.compile();
        })()
    });
    
    Ext.namespace('Ext.ux.layout');
    Ext.ux.layout.TableFormLayout = Ext.extend(Ext.layout.TableLayout, {
    	fieldTpl: Ext.layout.FormLayout.prototype.fieldTpl,
    
        renderItem : function(c, position, target) {
            if (c && !c.rendered) {
            	Ext.layout.FormLayout.prototype.renderItem.call(this, c, 0, Ext.get(this.getNextCell(c)));
            }
        }
    });
    Ext.Container.LAYOUTS['tableform'] = Ext.ux.layout.TableFormLayout;
    
    Ext.onReady(function()
    {
        Ext.QuickTips.init();
    
        var p = new Ext.Panel(
        {
            layout: 'tableform',
            title: 'Table-Form Layout',
            bodyStyle: 'padding:6px',
            renderTo: Ext.getBody(),
            layoutConfig: {columns:3},
            formConfig: // config options to be applied to each panel in each table cell
            {
                layoutConfig:
                {
                    labelSeparator: ''
                },
                bodyStyle: 'padding:0 3px',
                labelAlign: 'top',
                border: false
            },
            items:
            [
                {
                    xtype: 'textfield',
                    fieldLabel: 'Field 1',
                    name: 'Field1',
                    width: 115
                },
                {
                    xtype: 'textfield',
                    fieldLabel: 'Field 2',
                    name: 'Field2',
                    width: 115
                },
                {
                    xtype: 'textfield',
                    fieldLabel: 'Field 3',
                    name: 'Field3',
                    width: 115
                },
                {
                    xtype: 'textfield',
                    fieldLabel: 'Field 4',
                    name: 'Field4',
                    width: 115
                },
                {
                    colspan: 2,
                    xtype: 'textfield',
                    fieldLabel: 'Field 5',
                    name: 'Field5',
                    width: 236
                }
            ]
        });
    });
    </script>
    <body>
    </body>
    </html>

  7. #7
    Ext JS Premium Member
    Join Date
    Mar 2007
    Location
    NL
    Posts
    608
    Vote Rating
    1
    mdissel is on a distinguished road

      0  

    Default


    What's the reason of the override of Ext.layout.FormLayout.fieldTpl?

  8. #8
    Sencha - Ext JS Dev Team Animal's Avatar
    Join Date
    Mar 2007
    Location
    Notts/Redwood City
    Posts
    30,506
    Vote Rating
    54
    Animal has a spectacular aura about Animal has a spectacular aura about Animal has a spectacular aura about

      0  

    Default


    Because Ext.layout.FormLayout.prototype.renderItem uses this.fieldTpl which is only available in Ext.layout.FormLayout - and then, only after it has been invoked once - hence the override to ensure its always there in the prototype.

  9. #9
    Ext JS Premium Member
    Join Date
    Oct 2007
    Location
    Herndon, VA
    Posts
    265
    Vote Rating
    3
    durlabh is on a distinguished road

      0  

    Default


    I think we need to update the setContainer method also for tableform layout to be able to use properties such as labelWidth etc.
    Code:
    /**
     * Needed for tableform layout
     **/
    Ext.override(Ext.layout.FormLayout, {
        fieldTpl: (function() {
            var t = new Ext.Template(
                '<div class="x-form-item {5}" tabIndex="-1">',
                    '<label for="{0}" style="{2}" class="x-form-item-label">{1}{4}</label>',
                    '<div class="x-form-element" id="x-form-el-{0}" style="{3}">',
                    '</div><div class="{6}"></div>',
                '</div>'
            );
            t.disableFormats = true;
            return t.compile();
        })()
    });
    
    /**
     * Table form layout
     **/
    Ext.layout.TableFormLayout = Ext.extend(Ext.layout.TableLayout, {
        setContainer : function(ct){
            Ext.layout.TableFormLayout.superclass.setContainer.call(this, ct);
            if(ct.labelAlign){
                ct.addClass('x-form-label-'+ct.labelAlign);
            }
    
            if(ct.hideLabels){
                this.labelStyle = "display:none";
                this.elementStyle = "padding-left:0;";
                this.labelAdjust = 0;
            }else{
                this.labelSeparator = ct.labelSeparator || this.labelSeparator;
                ct.labelWidth = ct.labelWidth || 100;
                if(typeof ct.labelWidth == 'number'){
                    var pad = (typeof ct.labelPad == 'number' ? ct.labelPad : 5);
                    this.labelAdjust = ct.labelWidth+pad;
                    this.labelStyle = "width:"+ct.labelWidth+"px;";
                    this.elementStyle = "padding-left:"+(ct.labelWidth+pad)+'px';
                }
                if(ct.labelAlign == 'top'){
                    this.labelStyle = "width:auto;";
                    this.labelAdjust = 0;
                    this.elementStyle = "padding-left:0;";
                }
            }
        },
    
        fieldTpl: Ext.layout.FormLayout.prototype.fieldTpl,
    
        renderItem : function(c, position, target) {
            if (c && !c.rendered) {
                Ext.layout.FormLayout.prototype.renderItem.call(this, c, 0, Ext.get(this.getNextCell(c)));
            }
        }
    });
    Ext.Container.LAYOUTS['tableform'] = Ext.layout.TableFormLayout;

  10. #10
    Sencha Premium Member
    Join Date
    Jun 2008
    Posts
    51
    Vote Rating
    1
    mbajema is on a distinguished road

      0  

    Default Label Options

    Label Options


    Animal,

    Thanks for posting an alternative solution. However, I'm not sure how to make it work with labels on top. Ultimately, I'm not sure why Ext JS doesn't render labels with form fields in all layouts, but it is probably because it is relatively complex to handle all of the options for labels.

    In the forums, the response to attempting to use form fields in a table layout is always that you have to put an extra layer of containers specifying the "form" layout in each one and then putting the form fields in those containers. My approach was to just automate this so that each table/form didn't need so many nested containers in the code. I'm not sure why I had to make it a Panel, but my approach didn't work with the generic Container object.

    I would be interested in using a robust table/form layout if it is workable. Can you expand your solution to work with the various label options?
    Mark Bajema
    Youth Mentoring Software from Innovative Mentoring