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 User
    Join Date
    Feb 2008
    Posts
    57
    Vote Rating
    0
    ikk0 is on a distinguished road

      0  

    Default


    Hi,
    this is not working correctly for me.
    At first, you are using something like "Perseus" in your code.
    I never heard of that. Had to comment that out to get the code working.
    Then, in your PHP-Example you are using the _() function, with which you probably translate text in your application, but you should remove it in the example code.
    But after loading the Metadata from the Server, I get an alert (Firebug):

    Code:
    POST get-content.php5?formconfig=true (235ms)ext-base.js (line 10)
    c has no properties
    [Break on this error] }else if(!c.events){
    Any Idea?

  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


    Ok, try it now, should work.
    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 User
    Join Date
    Feb 2008
    Posts
    57
    Vote Rating
    0
    ikk0 is on a distinguished road

      0  

    Default


    Code:
    Ext.isArray is not a function
    [Break on this error] if(Ext.isArray(this.ignoreFields)) {
    Seems like this is not implemented in standard-Ext. Could you supply the code?

    Greetings,

  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


    What version of Ext are you running?
    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