How to create custom ExtJS form field component?

后端 未结 9 522
无人共我
无人共我 2020-12-02 11:34

I want to create custom ExtJS form field components using other ExtJS components in it (e.g. TreePanel). How can I do it most easily?

I\'ve read doc

相关标签:
9条回答
  • 2020-12-02 11:50

    Many of the answers either use the Mixin Ext.form.field.Field or just extends on some already made class that suits their needs - which is fine.

    But I do not recommend fully overwriting the setValue method, that is IMO really bad form!

    A lot more happens than just setting and getting the value, and if you fully overwrite it - well you will for instance mess up the dirty state, processing of rawValue etc..

    Two options here I guess, one is to callParent(arguments) inside the method you declare to keep things streamlined, or to at the end when you are done apply the inherited method from where ever you got it (mixin or extend).

    But do not just overwrite it with no regards for what that already made method does behind the scenes.

    Also remember that if you use other field types in your new class - then do set the isFormField property to false - otherwise your getValues method on the form will take those values and run with em!

    0 讨论(0)
  • 2020-12-02 11:53

    Here is an example of a custom panel that extends an Ext Panel. You can extend any component, check the docs for the fields, methods and events you can play with.

    Ext.ns('yournamespace');
    
    yournamespace.MyPanel = function(config) {
        yournamespace.MyPanel.superclass.constructor.call(this, config);
    } 
    
    Ext.extend(yournamespace.MyPanel, Ext.Panel, {
    
        myGlobalVariable : undefined,
    
        constructor : function(config) {
            yournamespace.MyPanel.superclass.constructor.apply(this, config);
        },
    
        initComponent : function() {
            this.comboBox = new Ext.form.ComboBox({
                fieldLabel: "MyCombo",
                store: someStore,
                displayField:'My Label',
                typeAhead: true,
                mode: 'local',
                forceSelection: true,
                triggerAction: 'all',
                emptyText:'',
                selectOnFocus:true,
                tabIndex: 1,
                width: 200
            });
    
            // configure the grid
            Ext.apply(this, {
                listeners: {
                    'activate': function(p) {
                        p.doLayout();
                     },
                     single:true
                },
    
                xtype:"form",
                border: false,
                layout:"absolute",
                labelAlign:"top",
                bodyStyle:"padding: 15px",
                width: 350,
                height: 75,
    
                items:[{
                    xtype:"panel",
                    layout:"form",
                    x:"10",
                    y:"10",
                    labelAlign:"top",
                    border:false,
                    items:[this.comboBox]
                },
                {
                    xtype:"panel",
                    layout:"form",
                    x:"230",
                    y:"26",
                    labelAlign:"top",
                    border:false,
                    items:[{
                        xtype:'button',
                        handler: this.someAction.createDelegate(this),
                        text: 'Some Action'
                    }]
                }]
            }); // eo apply
    
            yournamespace.MyPanel.superclass.initComponent.apply(this, arguments);
    
            this.comboBox.on('select', function(combo, record, index) {
                this.myGlobalVariable = record.get("something");
            }, this);
    
        }, // eo function initComponent
    
        someAction : function() {
            //do something
        },
    
        getMyGlobalVariable : function() {
            return this.myGlobalVariable;
        }
    
    }); // eo extend
    
    Ext.reg('mypanel', yournamespace.MyPanel);
    
    0 讨论(0)
  • 2020-12-02 11:56

    I've done this a few times. Here is the general process/pseudo-code I use:

    • Create an extension of field that provides the most useful re-use (typically Ext.form.TextField if you just want to get/set a string value)
    • In the afterrender of the field, hide the textfield, and create a wrapping element around this.el with this.wrap = this.resizeEl = this.positionEl = this.el.wrap()
    • Render any components to this.wrap (e.g. using renderTo: this.wrap in the config)
    • Override getValue and setValue to talk to the component(s) you rendered manually
    • You may need to do some manually sizing in a resize listener if your form's layout changes
    • Don't forget to cleanup any components you create in the beforeDestroy method!

    I can't wait to switch our codebase to ExtJS 4, where these kinds of things are easy.

    Good luck!

    0 讨论(0)
  • 2020-12-02 11:59

    Following the documentation at http://docs.sencha.com/ext-js/4-0/#/api/Ext.form.field.Base

    This code will create a reusable TypeAhead/Autocomplete style field for selecting a language.

    var langs = Ext.create( 'Ext.data.store', {
        fields: [ 'label', 'code' ],
        data: [
            { code: 'eng', label: 'English' },
            { code: 'ger', label: 'German' },
            { code: 'chi', label: 'Chinese' },
            { code: 'ukr', label: 'Ukranian' },
            { code: 'rus', label: 'Russian' }
        ]
    } );
    
    Ext.define( 'Ext.form.LangSelector', {
        extend: 'Ext.form.field.ComboBox',
        alias: 'widget.LangSelector',
        allowBlank: false,
        hideTrigger: true,
        width: 225,
        displayField: 'label',
        valueField: 'code',
        forceSelection: true,
        minChars: 1,
        store: langs
    } );
    

    You can use the field in a form simply by setting the xtype to the widget name:

    {
        xtype: 'LangSelector'
        fieldLabel: 'Language',
        name: 'lang'
    }
    
    0 讨论(0)
  • 2020-12-02 12:00

    Since the question was asked rather vague - I only can provide the basic pattern for ExtJS v4.

    Even if it's not too specific, it has the advance that it's rather universal like this:

    Ext.define('app.view.form.field.CustomField', {
        extend: 'Ext.form.field.Base',
        requires: [
            /* require further components */
        ],
    
        /* custom configs & callbacks */
    
        getValue: function(v){
            /* override function getValue() */
        },
    
        setValue: function(v){
            /* override function setValue() */
        },
    
        getSubTplData: [
           /* most likely needs to be overridden */
        ],
    
        initComponent: function(){
    
            /* further code on event initComponent */
    
            this.callParent(arguments);
        }
    });
    

    The file /ext/src/form/field/Base.js provides the names of all configs and functions that can be overridden.

    0 讨论(0)
  • 2020-12-02 12:02

    To extend @RobAgar 's answer, following a really simple Date Time field that I wrote for ExtJS 3 and it's quickport that I made for ExtJS 4. The important thing is the use of the Ext.form.field.Field mixin. This mixin provides a common interface for the logical behavior and state of form fields, including:

    Getter and setter methods for field values Events and methods for tracking value and validity changes Methods for triggering validation

    This can be used for combining multiple fields and let act them as one. For a total custom fieldtype I recommend to extend Ext.form.field.Base

    Here is the example that I mentioned above. It should shoe how easy this can be done even for something like a date object where we need to format the data within the getter and setter.

    Ext.define('QWA.form.field.DateTime', {
        extend: 'Ext.form.FieldContainer',
        mixins: {
            field: 'Ext.form.field.Field'
        },
        alias: 'widget.datetimefield',
        layout: 'hbox',
        width: 200,
        height: 22,
        combineErrors: true,
        msgTarget: 'side',
        submitFormat: 'c',
    
        dateCfg: null,
        timeCfg: null,
    
        initComponent: function () {
            var me = this;
            if (!me.dateCfg) me.dateCfg = {};
            if (!me.timeCfg) me.timeCfg = {};
            me.buildField();
            me.callParent();
            me.dateField = me.down('datefield')
            me.timeField = me.down('timefield')
    
            me.initField();
        },
    
        //@private
        buildField: function () {
            var me = this;
            me.items = [
            Ext.apply({
                xtype: 'datefield',
                submitValue: false,
                format: 'd.m.Y',
                width: 100,
                flex: 2
            }, me.dateCfg),
            Ext.apply({
                xtype: 'timefield',
                submitValue: false,
                format: 'H:i',
                width: 80,
                flex: 1
            }, me.timeCfg)]
        },
    
        getValue: function () {
            var me = this,
                value,
                date = me.dateField.getSubmitValue(),
                dateFormat = me.dateField.format,
                time = me.timeField.getSubmitValue(),
                timeFormat = me.timeField.format;
            if (date) {
                if (time) {
                    value = Ext.Date.parse(date + ' ' + time, me.getFormat());
                } else {
                    value = me.dateField.getValue();
                }
            }
            return value;
        },
    
        setValue: function (value) {
            var me = this;
            me.dateField.setValue(value);
            me.timeField.setValue(value);
        },
    
        getSubmitData: function () {
            var me = this,
                data = null;
            if (!me.disabled && me.submitValue && !me.isFileUpload()) {
                data = {},
                value = me.getValue(),
                data[me.getName()] = '' + value ? Ext.Date.format(value, me.submitFormat) : null;
            }
            return data;
        },
    
        getFormat: function () {
            var me = this;
            return (me.dateField.submitFormat || me.dateField.format) + " " + (me.timeField.submitFormat || me.timeField.format)
        }
    });
    
    0 讨论(0)
提交回复
热议问题