Hybrid View

  1. #1
    Sencha - Community Support Team jsakalos's Avatar
    Join Date
    Apr 2007
    Location
    Slovakia
    Posts
    27,520
    Vote Rating
    376
    jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future

      0  

    Default Ext.ux.MetaForm - A FormPanel configured by metadata received from server

    Ext.ux.MetaForm - A FormPanel configured by metadata received from server


    Hi all,

    I've run into need of a FormPanel that would be auto-configured by metadata received from server. As usually, I've written it; here is the first version:

    This is html file I've used for testing:
    HTML Code:
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <link rel="stylesheet" type="text/css" href="../ext/resources/css/ext-all.css">
        <script type="text/javascript" src="../ext/adapter/ext/ext-base.js"></script>
        <script type="text/javascript" src="../ext/ext-all-debug.js"></script>
        <script type="text/javascript" src="Ext.ux.MetaForm.js"></script>
    
        <!-- A Localization Script File comes here -->
        <script type="text/javascript">
    Ext.onReady(function() {
    
        var win = new Ext.Window({
             id:'metaform-win'
            ,layout:'fit'
            ,width:500
            ,height:300
            ,title:'Ext.ux.MetaForm'
            ,items:{
                 xtype:'metaform'
                ,url:'formconfig.php'
                ,buttons:[{
                     text:'Load'
                    ,handler:function() {
                        Ext.getCmp('metaform-win').items.get(0).getForm().load();
                    }
                },{
                     text:'Submit'
                    ,handler:function() {
                        Ext.getCmp('metaform-win').items.get(0).getForm().submit();
                    }
                }]
            }
        });
    
        win.show();
    });
        </script>
        <title>Ext.ux.MetaForm Example</title>
    </head>
    <body>
    </body>
    </html>
    Ext.ux.MetaForm code:

    PHP Code:
    // vim: ts=4:sw=4:nu:fdc=4:nospell
    /*global Ext */
    /**
     * @class Ext.ux.form.MetaForm
     * @extends Ext.form.FormPanel
     *
     * A FormPanel configured by metadata received from server
     *
     * @author    Ing. Jozef Sakáloš
     * @copyright (c) 2008, by Ing. Jozef Sakáloš
     * @version   1.3
     * @date      <ul>
     * <li>6. February 2007</li>
     * <li>6. March 2009</li>
     * </ul>
     * @revision  $Id: Ext.ux.form.MetaForm.js 625 2009-03-11 00:04:59Z jozo $
     *
     * @license Ext.ux.form.MetaForm is licensed under the terms of
     * the Open Source LGPL 3.0 license.  Commercial use is permitted to the extent
     * that the code/component(s) do NOT become part of another Open Source or Commercially
     * licensed development library or toolkit without explicit permission.
     * 
     * <p>License details: <a href="http://www.gnu.org/licenses/lgpl.html"
     * target="_blank">http://www.gnu.org/licenses/lgpl.html</a></p>
     *
     * @forum     25551
     * 
     * @donate
     * <form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank">
     * <input type="hidden" name="cmd" value="_s-xclick">
     * <input type="hidden" name="hosted_button_id" value="3430419">
     * <input type="image" src="https://www.paypal.com/en_US/i/btn/x-click-butcc-donate.gif" 
     * border="0" name="submit" alt="PayPal - The safer, easier way to pay online.">
     * <img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
     * </form>
     */

    Ext.ns('Ext.ux.form');

    /**
     * Creates new MetaForm
     * @constructor
     * @param {Object} config A config object
     */
    Ext.ux.form.MetaForm Ext.extend(Ext.form.FormPanel, {

        
    // {{{
        // config options
        /**
         * @cfg {Boolean/Object} autoInit
         * Load runs immediately after the form is rendered if autoInit is set. In the case of boolean true
         * the load runs with {meta:true} and in the case of object the load takes autoInit as argument 
         * (defaults to true)
         */
         
    autoInit:true

        
    /**
         * @cfg {Object} baseParams
         * Params sent with each request (defaults to undefined)
         */

        /**
         * @cfg {Boolean} border
         * True to display the borders of the panel's body element, false to hide them (defaults to false).  By default,
         * the border is a 2px wide inset border, but this can be further altered by setting {@link #bodyBorder} to false.
         */
        
    ,border:false

        
    /**
         * @cfg {Boolean} focusFirstField
         * True to try to focus the first form field on metachange (defaults to true)
         */
        
    ,focusFirstField:true

        
    /**
         * True to render the panel with custom rounded borders, false to render with plain 1px square borders (defaults to true).
         */
        
    ,frame:true

        
    /**
         * @cfg {String} loadingText
         * Localizable text for "Loading..."
         */
        
    ,loadingText:'Loading...'

        
    /**
         * @cfg {String} savingText
         * Localizable text for "Saving..."
         */
        
    ,savingText:'Saving...'

        
    /**
         * @cfg {Number} buttonMinWidth 
         * Minimum width of buttons (defaults to 90)
         */
        
    ,buttonMinWidth:90

        
    /**
         * @cfg {Number} columnCount
         * MetaForm has a column layout insise with this number of columns (defaults to 1)
         */
        
    ,columnCount:1

        
    /**
         * @cfg {Array} createButtons Array of buttons to create.
         * Valid values are ['meta', 'load', defaults', 'reset', 'save', 'ok', 'cancel'] or any subset of them
         * (defaults to undefined)
         */

        /**
         * @cfg {Object} data
         * Data object bound to this form. If both {@link #metaData} and data are set at config time
         * the data is bound and loaded on form render after metaData processing.  Read-only at run-time.
         */

        /**
         * True if meta data has been processed and fields have been created, false otherwise (read-only)
         * @property hasMeta
         * @type Boolean
         */
        
    ,hasMeta:false

        
    /**
         * @cfg {Array} ignoreFields Array of field names to ignore when received in metaData (defaults to undefined)
         */

        /**
         * @cfg {Object} metaData Meta data used to configure this form. If set it takes precedence over {@link #autoInit}
         * and server is not accessed to get meta data.
         */

        /**
         * @cfg {String} method Sever access method. 'GET' or 'POST' (if undefined 'POST' is used)
         */

        /**
         * @cfg {String} url URL for loading an submitting the form (defaults to undefined)
         */
        // }}}
        // {{{
        /**
         * Runs after the meta data has been processed and the form fields have been created.
         * Override it to add your own extra processing if you need (defaults to Ext.emptyFn)
         * @method afterMetaChange
         */
        
    ,afterMetaChange:Ext.emptyFn
        
    // }}}
        // {{{
        /**
         * Runs after bound data is updated. Override to add any extra processing you may need
         * after the bound data is updated (defaults to Ext.emptyFn)
         * @param {Ext.ux.form.MetaForm} form This form
         * @param {Object} data Updated bound data
         */
        
    ,afterUpdate:Ext.emptyFn
        
    // }}}
        // {{{
        
    ,applyDefaultValues:function(o) {
            if(
    'object' !== typeof o) {
                return;
            }
            for(var 
    name in o) {
                if(
    o.hasOwnProperty(name)) {
                    var 
    field this.form.findField(name);
                    if(
    field) {
                        
    field.defaultValue o[name];
                    }
                }
            }
        } 
    // eo function applyDefaultValues
        // }}}
        // {{{
        /**
         * @private
         * Changes order of execution in Ext.form.Action.Load::success
         * to allow reading of data in this server request (otherwise data would
         * be loaded to the form before onMetaChange is run from actioncomplete event
         */
        
    ,beforeAction:function(formaction) {
            
    action.success = function(response) {
                var 
    result this.processResponse(response);
                if(
    result === true || !result.success || !result.data){
                    
    this.failureType Ext.form.Action.LOAD_FAILURE;
                    
    this.form.afterAction(thisfalse);
                    return;
                }
                
    // original
    //            this.form.clearInvalid();
    //            this.form.setValues(result.data);
    //            this.form.afterAction(this, true);

                
    this.form.afterAction(thistrue);
                
    this.form.clearInvalid();
                
    this.form.setValues(result.data);
            };
        } 
    // eo function beforeAction
        // }}}
        // {{{
        /**
         * Backward compatibility function, calls {@link #bindData} function
         * @param {Object} data 
         * A reference to an external data object. The idea is that form can display/change an external object
         */
        
    ,bind:function(data) {
            
    this.bindData(data);
        } 
    // eo function bind
        // }}}
        // {{{
        /**
         * @param {Object} data 
         * A reference to an external data object. The idea is that form can display/change an external object
         */
        
    ,bindData:function(data) {
            
    this.data data;
            
    this.form.setValues(this.data);
        } 
    // eo function bindData
        // }}}
        // {{{
        /**
         * Closes the parent if it is a window
         * @private
         */
        
    ,closeParentWindow:function() {
            if(
    this.ownerCt && this.ownerCt.isXType('window')) {
                
    this.ownerCt[this.ownerCt.closeAction]();
            }
        } 
    // eo function closeParentWindow
        // }}}
        // {{{
        /**
         * Returns button thet has the given name
         * @param {String} name Button name
         * @return {Ext.Button/Null} Button found or null if not found
         */
        
    ,findButton:function(name) {
            var 
    btn null;
            
    Ext.each(this.buttons, function(b) {
                if(
    name === b.name) {
                    
    btn b;
                }
            });
            return 
    btn;
        } 
    // eo function findButton
        // }}}
        // {{{
        /**
         * Returns the button. This funcion is undefined by default, supply it if you want an automated button creation.
         * @method getButton
         * @param {String} name A symbolic button name
         * @param {Object} config The button config object
         * @return {Ext.Button} The created button
         */
        // getButton
        // }}}
        // {{{
        /**
         * override this if you want a special buttons config
         */
        
    ,getButtons:function() {
            var 
    buttons = [];
            if(
    Ext.isArray(this.createButtons)) {
                
    Ext.each(this.createButtons, function(name){
                    
    buttons.push(this.getButton(name, {
                         
    handler:this.onButtonClick
                        
    ,scope:this
                        
    ,minWidth:this.buttonMinWidth
                        
    ,name:name
                    
    }));
                }, 
    this);
            }
            return 
    buttons;
        } 
    // eo function getButtons
        // }}}
        // {{{
        
    ,getOptions:function(o) {
            
    || {};
            var 
    options = {
                 
    url:this.url
                
    ,method:this.method || 'POST'
            
    };
            
    Ext.apply(optionso);
            var 
    params this.baseParams Ext.ux.util.clone(this.baseParams) : {};
            
    options.params Ext.apply(paramso.params);
            return 
    options;
        } 
    // eo function getOptions
        // }}}
        // {{{
        /**
         * Returns values calling the individual fields' getValue() methods
         * @return {Object} object with name/value pairs
         */
        
    ,getValues:function() {
            var 
    values = {};
            
    this.form.items.each(function(f) {
                
    values[f.name] = f.getValue();
            });
            return 
    values;
        } 
    // eo function getValues
        // }}}
        // {{{
        
    ,initComponent:function() {

            var 
    config = {
                
    items:this.items || {}
            };
            if(
    'function' === typeof this.getButton) {
                
    config.buttons this.getButtons();
            }

            
    // apply config
            
    Ext.apply(thisExt.apply(this.initialConfigconfig));

            
    // call parent
            
    Ext.ux.form.MetaForm.superclass.initComponent.apply(thisarguments);
            
            
    // add events
            
    this.addEvents(
                
    /**
                 * @event beforemetachange
                 * Fired before meta data is processed. Return false to cancel the event
                 * @param {Ext.ux.form.MetaForm} form This form
                 * @param {Object} metaData The meta data being processed
                 */
                 
    'beforemetachange'
                
    /**
                 * @event metachange
                 * Fired after meta data is processed and form fields are created.
                 * @param {Ext.ux.form.Metadata} form This form
                 * @param {Object} metaData The meta data processed
                 */
                
    ,'metachange'
                
    /**
                 * @event beforebuttonclick
                 * Fired before the button click is processed. Return false to cancel the event
                 * @param {Ext.ux.form.MetaForm} form This form
                 * @param {Ext.Button} btn The button clicked
                 */
                
    ,'beforebuttonclick'
                
    /**
                 * @event buttonclick
                 * Fired after the button click has been processed
                 * @param {Ext.ux.form.MetaForm} form This form
                 * @param {Ext.Button} btn The button clicked
                 */
                
    ,'buttonclick'
            
    );

            
    // install event handlers on basic form
            
    this.form.on({
                 
    beforeaction:{scope:thisfn:this.beforeAction}
                ,
    actioncomplete:{scope:thisfn:function(formaction) {
                    
    // (re) configure the form if we have (new) metaData
                    
    if('load' === action.type && action.result.metaData) {
                        
    this.onMetaChange(thisaction.result.metaData);
                    }
                    
    // update bound data on successful submit
                    
    else if('submit' === action.type) {
                        
    this.updateBoundData();
                    }
                }}
            });
            
    this.form.trackResetOnLoad true;

        } 
    // eo function initComponent
        // }}}
        // {{{
        
    ,load:function(o) {
            var 
    options this.getOptions(o);
            if(
    this.loadingText) {
                
    options.waitMsg this.loadingText;
            }
            
    this.form.load(options);
        } 
    // eo function load
        // }}}
        // {{{
        /**
         * Called in the scope of this form when user clicks a button. Override it if you need a different
         * functionality of the button handlers.
         * <i>Note: Buttons created by MetaForm has name property that matches {@link #createButtons} names</i>
         * @param {Ext.Button} btn The button clicked. 
         * @param {Ext.EventObject} e Click event
         */
        
    ,onButtonClick:function(btne) {
            if(
    false === this.fireEvent('beforebuttonclick'thisbtn)) {
                return;
            }
            switch(
    btn.name) {
                case 
    'meta':
                    
    this.load({params:{meta:true}});
                break;

                case 
    'load':
                    
    this.load({params:{meta:!this.hasMeta}});
                break;

                case 
    'defaults':
                    
    this.setDefaultValues();
                break;

                case 
    'reset':
                    
    this.form.reset();
                break;

                case 
    'save':
                    
    this.updateBoundData();
                    
    this.submit();
                    
    this.closeParentWindow();
                break;

                case 
    'ok':
                    
    this.updateBoundData();
                    
    this.closeParentWindow();
                break;

                case 
    'cancel':
                    
    this.closeParentWindow();
                break;
            }
            
    this.fireEvent('buttonclick'thisbtn);
        } 
    // eo function onButtonClick
        // }}}
        // {{{
        /**
         * Override this if you need a custom functionality
         *
         * @param {Ext.FormPanel} this
         * @param {Object} meta Metadata
         * @return void
         */
        
    ,onMetaChange:function(formmeta) {
            if(
    false === this.fireEvent('beforemetachange'thismeta)) {
                return;
            }
            
    this.removeAll();
            
    this.hasMeta false;

            
    // declare varables
            
    var columnscolIndextabIndexignore = {};

            
    // add column layout
            
    this.add(new Ext.Panel({
                 
    layout:'column'
                
    ,anchor:'100%'
                
    ,border:false
                
    ,defaults:(function(){
                    
    this.columnCount meta.formConfig meta.formConfig.columnCount || this.columnCount this.columnCount;
                    return 
    Ext.apply({}, meta.formConfig || {}, {
                         
    columnWidth:1/this.columnCount
                        
    ,autoHeight:true
                        
    ,border:false
                        
    ,hideLabel:true
                        
    ,layout:'form'
                    
    });
                }).
    createDelegate(this)()
                ,
    items:(function(){
                    var 
    items = [];
                    for(var 
    0this.columnCounti++) {
                        
    items.push({
                             
    defaults:this.defaults
                            
    ,listeners:{
                                
    // otherwise basic form findField does not work
                                
    add:{scope:thisfn:this.onAdd}
                            }
                        });
                    }
                    return 
    items;
                }).
    createDelegate(this)()
            }));
            
            
    columns this.items.get(0).items;
            
    colIndex 0;
            
    tabIndex 1;

            if(
    Ext.isArray(this.ignoreFields)) {
                
    Ext.each(this.ignoreFields, function(f) {
                    
    ignore[f] = true;
                });
            }
            
    // loop through metadata colums or fields
            // format follows grid column model structure
            
    Ext.each(meta.columns || meta.fields, function(item) {
                if(
    true === ignore[item.name]) {
                    return;
                }
                var 
    config Ext.apply({}, item.editor, {
                     
    name:item.name || item.dataIndex
                    
    ,fieldLabel:item.fieldLabel || item.header
                    
    ,defaultValue:item.defaultValue
                    
    ,xtype:item.editor && item.editor.xtype item.editor.xtype 'textfield'
                
    });

                
    // handle regexps
                
    if(config.editor && config.editor.regex) {
                    
    config.editor.regex = new RegExp(item.editor.regex);
                }

                
    // to avoid checkbox misalignment
                
    if('checkbox' === config.xtype) {
                    
    Ext.apply(config, {
                          
    boxLabel:' '
                         
    ,checked:item.defaultValue
                    
    });
                }
                if(
    meta.formConfig.msgTarget) {
                    
    config.msgTarget meta.formConfig.msgTarget;
                }

                
    // add to columns on ltr principle
                
    config.tabIndex tabIndex++;
                
    columns.get(colIndex++).add(config);
                
    colIndex colIndex === this.columnCount colIndex;

            }, 
    this);
            if(
    this.rendered && 'string' !== typeof this.layout) {
                
    this.el.setVisible(false);
                
    this.doLayout();
                
    this.el.setVisible(true);
            }
            
    this.hasMeta true;
            if(
    this.data) {
                
    // give DOM some time to settle
                
    (function() {
                    
    this.form.setValues(this.data);
                }.
    defer(1this))
            }
            
    this.afterMetaChange();
            
    this.fireEvent('metachange'thismeta);

            
    // try to focus the first field
            
    if(this.focusFirstField) {
                var 
    firstField this.form.items.itemAt(0);
                if(
    firstField && firstField.focus) {
                    var 
    delay this.ownerCt && this.ownerCt.isXType('window') ? 1000 100;
                    
    firstField.focus(firstField.selectOnFocusdelay);
                }
            }
        } 
    // eo function onMetaChange
        // }}}
        // {{{
        
    ,onRender:function() {
            
    // call parent
            
    Ext.ux.form.MetaForm.superclass.onRender.apply(thisarguments);

            
    this.form.waitMsgTarget this.el;

            if(
    this.metaData) {
                
    this.onMetaChange(thisthis.metaData);
                if(
    this.data) {
                    
    this.bindData(this.data);
                }
            }
            else if(
    true === this.autoInit) {
                
    this.load(this.getOptions({params:{meta:true}}));
            }
            else if (
    'object' === typeof this.autoInit) {
                
    this.load(this.autoInit);
            }

        } 
    // eo function onRender
        // }}}
        // {{{
        /**
         * @private
         * Removes all items from both formpanel and basic form
         */
        
    ,removeAll:function() {
            
    // remove border from header
            
    var hd this.body.up('div.x-panel-bwrap').prev();
            if(
    hd) {
                
    hd.applyStyles({border:'none'});
            }
            
    // remove form panel items
            
    this.items.each(this.removethis);

            
    // remove basic form items
            
    this.form.items.clear();
        } 
    // eo function removeAllItems
        // }}}
        // {{{
        
    ,reset:function() {
            
    this.form.reset();
        } 
    // eo function reset
        // }}}
        // {{{
        
    ,setDefaultValues:function() {
            
    this.form.items.each(function(item) {
                
    item.setValue(item.defaultValue);
            });
        } 
    // eo function setDefaultValues
        // }}}
        // {{{
        
    ,submit:function(o) {
            var 
    options this.getOptions(o);
            if(
    this.savingText) {
                
    options.waitMsg this.savingText;
            }
            
    this.form.submit(options);
        } 
    // eo function submit
        // }}}
        // {{{
        /**
         * Updates bound data
         */
        
    ,updateBoundData:function() {
            if(
    this.data) {
                
    Ext.apply(this.datathis.getValues());
                
    this.afterUpdate(thisthis.data);
            }
        } 
    // eo function updateBoundData
        // }}}
        // {{{
        
    ,beforeDestroy:function() {
            if(
    this.data) {
                
    this.data null;
            }
            
    Ext.ux.form.MetaForm.superclass.beforeDestroy.apply(thisarguments);
        } 
    // eo function beforeDestroy
        // }}}

    });

    // register xtype
    Ext.reg('metaform'Ext.ux.form.MetaForm);

    // eof 
    And for those using PHP, here is PHP script I've used for testing; hopefully it gives at least an idea for non-PHP users on how the returned json should look like:

    PHP Code:
    <?php

    $formConfig 
    = array(
         
    "labelAlign"=>"left"
        
    ,"columnCount"=>2
        
    ,"labelWidth"=>80
        
    ,"defaults"=>array(
             
    "width"=>130
        
    )
    );
    $fields = array(
        
    // company name
        
    array(
             
    "name"=>"compName"
            
    ,"fieldLabel"=>"Company"
            
    ,"editor"=>array(
                 
    "allowBlank"=>false
            
    )
        )
        ,array(
             
    "name"=>"compForm"
             
    ,"fieldLabel"=>"Legal Form"
             
    ,"editor"=>array(
                 
    "allowBlank"=>false
             
    )
        )
        ,array(
            
    "name"=>"clientFrom"
            
    ,"fieldLabel"=>"Client Since"
            
    ,"editor"=>array(
                 
    "xtype"=>"datefield"
                
    ,"format"=>"j.n.y"
            
    )
        )
        ,array(
            
    "name"=>"clientTill"
            
    ,"fieldLabel"=>"Client Till"
            
    ,"editor"=>array(
                 
    "xtype"=>"datefield"
                
    ,"format"=>"j.n.y"
            
    )
        )
        ,array(
            
    "name"=>"compNote"
            
    ,"fieldLabel"=>"Note"
            
    ,"editor"=>array(
                 
    "xtype"=>"textarea"
            
    )
        )
    );
    $config = array(
         
    "success"=>true
        
    ,"metaData"=>array(
             
    "fields"=>$fields
            
    ,"formConfig"=>$formConfig
        
    )
        ,
    "data"=>array(
             
    "compName"=>"My Company"
            
    ,"compNote"=>"Company Note"
            
    ,"clientFrom"=>"1.2.08"
        
    )
    );
    echo 
    json_encode($config);

    // end of file
    ?>
    And finally, resulting json:

    Code:
    {"success":true,"metaData":{"fields":[{"name":"compName","fieldLabel":"Firma","editor":{"allowBlank":false}},{"name":"compForm","fieldLabel":"Legal Form","editor":{"allowBlank":false}},{"name":"clientFrom","fieldLabel":"Client Since","editor":{"xtype":"datefield","format":"j.n.y"}},{"name":"clientTill","fieldLabel":"Client Till","editor":{"xtype":"datefield","format":"j.n.y"}},{"name":"compNote","fieldLabel":"Note","editor":{"xtype":"textarea"}}],"formConfig":{"labelAlign":"left","columnCount":2,"labelWidth":80,"defaults":{"width":130}}},"data":{"compName":"My Company","compNote":"Company Note","clientFrom":"1.2.08"}}
    Enjoy.
    Jozef Sakalos, aka Saki

    Education, extensions and services for developers at new http://extjs.eu
    News: Grid Search Plugin, ExtJS 5 Complex Data Binding using MVVM


  2. #2
    Ext JS Premium Member
    Join Date
    May 2007
    Posts
    64
    Vote Rating
    0
    MeDavid is on a distinguished road

      0  

    Default


    Hi,

    Maybe a good idea to use annotations / reflection, so that you can create froms and grids based on your php data classes?

    PHP Code:
    class Person {
       
    /**
        * @GUI(label=>"First name", width=>200);
        * @Validation(allowEmpty=>true, maxLength=>100)
        */
       
    public $firstName;



  3. #3
    Sencha - Community Support Team jsakalos's Avatar
    Join Date
    Apr 2007
    Location
    Slovakia
    Posts
    27,520
    Vote Rating
    376
    jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future

      0  

    Default


    Sure. I'm not creating data for MetaForms with the PHP like above in real application. I've chosen the above example as it clearly illustrates the structure of JSON that is understood by the MetaForm.

    Anyway, MetaForm as client side javascript class doesn't care how, or in which language, is created JSON it accepts the format of.
    Jozef Sakalos, aka Saki

    Education, extensions and services for developers at new http://extjs.eu
    News: Grid Search Plugin, ExtJS 5 Complex Data Binding using MVVM


  4. #4
    Ext User precariouspanther's Avatar
    Join Date
    Feb 2008
    Location
    Sydney, Australia
    Posts
    37
    Vote Rating
    0
    precariouspanther is on a distinguished road

      0  

    Default


    Thanks for the great plugin JSA. Just one small addition:

    PHP Code:

            
    // loop through metadata colums or fields
            // format follows grid column model structure
            
    Ext.each(meta.columns || meta.fields, function(item) {
                if(
    item.editor.regex){
                    
    //alert(item.editor.regex);
                    
    item.editor.regex= new RegExp(item.editor.regex);
                }
                
                var 
    config Ext.apply({}, item.editor, {
                     
    name:item.name || item.dataIndex
                    
    ,fieldLabel:item.fieldLabel || item.header
                    
    ,xtype:item.editor && item.editor.xtype item.editor.xtype 'textfield'
                
    }); 
    This will allow regex validation to be passed from the server config as well as the json gets evaled as a string rather than a regex object.

  5. #5
    Sencha - Community Support Team jsakalos's Avatar
    Join Date
    Apr 2007
    Location
    Slovakia
    Posts
    27,520
    Vote Rating
    376
    jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future

      0  

    Default


    Right. I've incorporated it to the source. BTW, I've been working on improvement of MetaForm a lot recently so I'm posting new version in the first post.

    Cheers.
    Jozef Sakalos, aka Saki

    Education, extensions and services for developers at new http://extjs.eu
    News: Grid Search Plugin, ExtJS 5 Complex Data Binding using MVVM


  6. #6
    Ext User precariouspanther's Avatar
    Join Date
    Feb 2008
    Location
    Sydney, Australia
    Posts
    37
    Vote Rating
    0
    precariouspanther is on a distinguished road

      0  

    Default


    Ooo very nice, thanks for the updates.

  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


    Why are you overriding the getValues() function? this override doesn't return all the fieldvalues if for example fieldsets are used inside the formpanel..

  8. #8
    Sencha - Community Support Team jsakalos's Avatar
    Join Date
    Apr 2007
    Location
    Slovakia
    Posts
    27,520
    Vote Rating
    376
    jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future

      0  

    Default


    It is not overrinden method it is added method. FormPanel, the MetaForm is the extension of, doesn't have its own getValues method. getValues method is defined in the underlying BasicForm that uses Ajax.serializeForm that was not good for my purposes.

    It is well known fact that if you add a component that is not formField to a FormPanel it is not added as item to underlying BasicForm (see FormPanel onAdd method). This is fiexed in MetaForm by lines:
    PHP Code:
                            ,listeners:{
                                
    // otherwise basic form findField does not work
                                
    add:{scope:thisfn:this.onAdd}
                            } 
    Deeper nested structures, as fields in fieldsets, are not handled by the above fix, though.

    The conclusion is: you can either use MetaForm::getValues() if it suits you or you can use MetaForm::getForm()::getValues() that is untouched.
    Jozef Sakalos, aka Saki

    Education, extensions and services for developers at new http://extjs.eu
    News: Grid Search Plugin, ExtJS 5 Complex Data Binding using MVVM


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

      0  

    Default


    Quote Originally Posted by jsakalos View Post
    The conclusion is: you can either use MetaForm::getValues() if it suits you or you can use MetaForm::getForm()::getValues() that is untouched.
    Thanks for the explantion. Why didn't the serializeForm fit into your purpose?

  10. #10
    Sencha - Community Support Team jsakalos's Avatar
    Join Date
    Apr 2007
    Location
    Slovakia
    Posts
    27,520
    Vote Rating
    376
    jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future

      0  

    Default


    I guess it was because it didn't return unchecked checkboxes or something of the sort.
    Jozef Sakalos, aka Saki

    Education, extensions and services for developers at new http://extjs.eu
    News: Grid Search Plugin, ExtJS 5 Complex Data Binding using MVVM


Turkiyenin en sevilen filmlerinin yer aldigi xnxx internet sitemiz olan ve porn sex tarzi bir site olan mobil porno izle sitemiz gercekten dillere destan bir durumda herkesin sevdigi bir site olarak tarihe gececege benziyor. Sitenin en belirgin ozelliklerinden birisi de Turkiyede gercekten kaliteli ve muntazam, duzenli porno izle siteleri olmamasidir. Bu yuzden iste. Ayrica en net goruntu kalitesine sahip adresinde yayinlanmaktadir. Mesela diğer sitelerimizden bahsedecek olursak, en iyi hd porno video arşivine sahip bir siteyiz. "The Best anal porn videos and slut anus, big asses movies set..." hd porno faketaxi