Threaded View

  1. #1
    Sencha User
    Join Date
    May 2011
    Location
    Toronto
    Posts
    13
    Vote Rating
    -2
    SenchaGuru has a little shameless behaviour in the past

      -1  

    Lightbulb Extjs 4 Dynamic Model

    Extjs 4 Dynamic Model


    Hi all

    I am building an application where the user can generate tables on the fly. The description of these tables are stored at the back-end.

    I needed to generate models from these descriptions and be able to use data grid objects to manipulate the data (crud operations).

    I have looked in this forum for a solution to this as I had realized that the current ExtJS 4 does not support adding fields dynamically to a model or a store, .. but I had no luck finding something that works for what I needed (in Extjs4).

    Anyways, I came up with a solution using 'eval' that does exactly what I wanted , .. and I wanted to share it with you.

    Here it is,..

    Code:
    Ext.Loader.setConfig({
        enabled: true
    });
    Ext.Loader.setPath('Ext.ux', 'http://dev.sencha.com/deploy/ext-4.0.1/examples/ux');
    Ext.require([
        'Ext.form.*',
        'Ext.data.*',
        'Ext.grid.*',
        'Ext.ux.grid.FiltersFeature',
        'Ext.layout.container.Column'
        ]);
    
    // This data can be pulled off a back-end database
    // Used to generate a model and a data grid
    var records = [{
        data:{
            "dataIndex":"first",
            "name":"First Name",
            "type":"string"
        }
    },{
        data:{
            "dataIndex":"last",
            "name":"Last Name",
            "type":"String"
        }
    },{
        data:{
            "dataIndex":"email",
            "name":"Email",
            "type":"string"
        }
    }];
    
    // Lookup table (type => xtype)
    var type_lookup = new Object;
    type_lookup['int'] = 'numberfield';
    type_lookup['float'] = 'numberfield';
    type_lookup['string'] = 'textfield';
    type_lookup['date'] = 'datefield';
    type_lookup['boolean'] = 'checkbox';
    
    // Skeleton store
    var store_template = {
        autoLoad: true,
        autoSync: true,
        remoteFilter: false,
        
        // DATA is inserted here for the example to work on local drive (use proxy below)
        data:[{id:1,first:"Fred",last:"Flintstone",email:"fred@flintstone.com"},
              {id:2,first:"Wilma",last:"Flintstone",email:"wilma@flintstone.com"},
              {id:3,first:"Pebbles",last:"Flintstone",email:"pebbles@flintstone.com"},
              {id:4,first:"Barney",last:"Rubble",email:"barney@rubble.com"},
              {id:5,first:"Betty",last:"Rubble",email:"betty@rubble.com"},
              {id:6,first:"BamBam",last:"Rubble",email:"bambam@rubble.com"}],
        proxy: {
            type: 'rest',
            url: 'http://dev.sencha.com/deploy/ext-4.0.1/examples/restful/app.php/users',
            reader: {
                type: 'json',
                root: 'data'
            },
            writer: {
                type: 'json'
            }
        }
    };
    
    // Skeleton grid (_PLUGINS_ & _STORE_, are placeholders)
    var grid_template = {
        columnWidth: 1,
        plugins: '_PLUGINS_',
        height: 300,
        store: '_STORE_'
    }
    
    // Skeleton window (_ITEMS_ is a placeholder)
    var window_template = {
        title: 'Dynamic Model / Window',
        height: 400,
        width: 750,
        layout: 'fit',
        items: '_ITEMS_'
    }
    
    // Generate a model dynamically, provide fields
    function modelFactory(name,fields){
        model =  {
            extend: 'Ext.data.Model',
            fields: fields
        };
        eval("Ext.define('"+name+"',"+Ext.encode(model)+");");
    }
    
    // Generate a dynamic store
    function storeFactory(name,template,model){
        template.model = model;
        eval(name+" = Ext.create('Ext.data.Store',"+Ext.encode(template)+");");
    }
    
    // Generate a dynamic grid, .. store name is appended as a string because otherwise, Ext.encode
    // will cause 'too much recursion' error (same for plugins)
    function gridFactory(name,template,store,plugins){
        script =  name+" = Ext.create('Ext.grid.Panel', "+Ext.encode(template)+");";
        script = script.replace("\"_STORE_\"", store);
        script = script.replace("\"_PLUGINS_\"", plugins);
        eval(script);
    }
    // Generate a dynamic window, .. items are appended as a string to avoid Ext.encode error
    function windowFactory(winName,winTemp,items){
        script += winName+" = Ext.create('Ext.window.Window',"+Ext.encode(winTemp)+").show();";
        script = script.replace("\"_ITEMS_\"", items);
        eval(script);
    }
    
    // Generate a model, a store a grid and a window dynamically from a record list!
    function generateDynamicModel(records){
        
        fields = [{
            name: 'id',
            type: 'int',
            useNull:true
        }];
    
        columns = [{
            text: 'ID',
            sortable: true,
            dataIndex: 'id'
        }];
    
        for (var i = 0; i < records.length; i++) {
    
            fields[i+1] =  {
                name: records[i].data.dataIndex,
                type: records[i].data.type
            };
    
            columns[i+1] = {
                text: records[i].data.name,
                sortable: true,
                dataIndex: records[i].data.dataIndex,
                field:  {
                    xtype: type_lookup[records[i].data.type]
                }
            };
        }
    
        grid_template.columns = columns;
    
        modelFactory('myModel',fields);
        storeFactory('myStore',store_template,'myModel');
        gridFactory('myGrid',grid_template,'myStore','[rowEditing]');
        windowFactory('myWindow',window_template,'[myGrid]');
    
        // Direct access to the store created above 
        myStore.load();
    }
    
    Ext.onReady(function(){
        rowEditing = Ext.create('Ext.grid.plugin.RowEditing');
        generateDynamicModel(records);
    });
    I never used 'eval' to such an extend, but it works surprisingly well,..

    You can also download the working example (attached).

    Cheers

    Adnan
    Attached Files