Extjs Form with dynamically shown/hidden fields on combo selection

sasklacz picture sasklacz · Jun 18, 2012 · Viewed 21.8k times · Source

Using Ext 4.1 I'd like to create a form with select combo, and depending on the currently selected option different subfields would be shown/hidden. Example below :

enter image description here

Right now I have a combo and a set of two date fields that are hidden on render. When a combo value is changed I have an event listener that will display those fields. But I'm not sure if it's the best method to tackle this. Would a fieldset work better in this case ?

Ext.define('TooltipForm', {
    extend: 'Ext.form.Panel',
    layout: {
        type: 'vbox',
        align: 'stretch'
    },
    border: false,
    bodyPadding: 10,

    initComponent: function(){
        this.on('afterrender', this.onAfterRender, this);

        this.callParent(arguments);
    },

    onAfterRender: function(){
        this.items.each(function(item){
            item.on('change', this.onChange, this);
        }, this);
    },

    onChange: function(field, newValue){
        if (field.name === 'range'){
            switch(newValue){
                case 'fit':
                    console.log('fit view');
                    break;
                case 'complete':
                    console.log('complete view');
                    break;
                case 'date range':
                    console.log('date range view');
                    break;
            }
        }
    },

    fieldDefaults: {
        labelAlign: 'top',
        labelWidth: 100,
        labelStyle: 'font-weight:bold'
    },
    items: [
        {
            width:          50,
            xtype:          'combo',
            mode:           'local',
            value:          'fit',
            triggerAction:  'all',
            forceSelection: true,
            editable:       false,
            fieldLabel:     me.rangeFieldLabel,
            name:           'range',
            queryMode:      'local',
            store:          ['fit', 'complete', 'date range']
        },
        {
            width:50,
            xtype: 'datefield',
            fieldLabel: 'date from',
            name: 'datefrom',
            hidden: true
        },
        {
            width:50,
            xtype: 'datefield',
            fieldLabel: 'date to',
            name: 'dateto',
            hidden:true,
        }
    ]
});

Answer

Evan Trimboli picture Evan Trimboli · Jun 19, 2012

Something along these lines:

Ext.define('TooltipForm', {
    extend: 'Ext.form.Panel',
    layout: {
        type: 'vbox',
        align: 'stretch'
    },
    border: false,
    bodyPadding: 10,
    rangeFieldLabel: 'Foo',

    initComponent: function() {
        Ext.apply(this, {
            fieldDefaults: {
                labelAlign: 'top',
                labelWidth: 100,
                labelStyle: 'font-weight:bold'
            },
            items: [{
                itemId: 'range',
                width: 50,
                xtype: 'combo',
                value: 'fit',
                triggerAction: 'all',
                forceSelection: true,
                editable: false,
                fieldLabel: this.rangeFieldLabel,
                name: 'range',
                queryMode: 'local',
                store: ['fit', 'complete', 'date range']
            }, {
                itemId: 'dateFrom',
                width: 50,
                xtype: 'datefield',
                fieldLabel: 'date from',
                name: 'datefrom',
                hidden: true
            }, {
                itemId: 'dateTo',
                width: 50,
                xtype: 'datefield',
                fieldLabel: 'date to',
                name: 'dateto',
                hidden: true,
            }]
        });

        this.callParent(arguments);
        this.child('#range').on('change', this.onChange, this);
    },

    onChange: function(field, newValue) {
        switch(newValue) {
            case 'fit':
                console.log('fit view');
                // do something else
                break;
            case 'complete':
                this.child('#dateFrom').hide();
                this.child('#dateTo').hide();
                break;
            case 'date range':
                this.child('#dateFrom').show();
                this.child('#dateTo').show();
                break;
        }
    },
});

Ext.onReady(function(){
    new TooltipForm({
        renderTo: document.body
    });
});