3
votes

I want to create my Model fields dynamically (in ExtJS 4). For instance, sometimes it is 0 to 3 and sometimes it is 0 to 7. This data comes from a JSON file (and store). This is my Model:

Ext.define('MyApp.model.User', {
    extend: 'Ext.data.Model',
    fields: ['0','1','2','3','4','5']
});

I tried many ways to get Model manually and create fields, but when it comes to a grid, I have empty rows of data without any errors. For example 8 empty rows in a grid.

Any help would be appreciated

4
And what fields are coming from the server? And why exactly are they different each time?sha
Thank you sha. JSON file contains Arrays of data and these are Array Indexes. They are different each time, because it is user define.Vahid
Here's an example of doing this following the MVC pattern with ExtJS 4.1egerardus

4 Answers

6
votes

I generate my model dynamically using the records returned by a store load callback. Here's how I create fields dynamically using the records.

roomTypesStore_Loaded: function (records) {
    var roomType;
    var fields = [
        { name: 'Id', type: 'int' },
        { name: 'Date', type: 'date' }
    ];

    for (var i = 0; i < records.length; i++) {
        roomType = records[i].data;
        fields[2 + (3 * i) + 0] = { name: roomType.Name + 'Rates', type: 'string' };
        fields[2 + (3 * i) + 1] = { name: roomType.Name + 'Selling', type: 'string' };
        fields[2 + (3 * i) + 2] = { name: roomType.Name + 'Booked', type: 'string' };
    }

    var model = {
        extend: 'Ext.data.Model',
        fields: fields
    };
    Ext.define('HEB.store.Schedule', model);
    var scheduleGrid = this.getScheduleGrid();
    var scheduleStore = this.getScheduleStore();
    if (scheduleGrid != null && scheduleStore != null) {
        scheduleGrid.reconfigure(scheduleStore, columns);
    }
},
0
votes

Create a model with maximum number of fields (say from 0 to 15 if you know that 15 will be the max you will receive from the server).

ExtJs is very forgivable when model doesn't match server response exactly. You should still got records created, just some fields will be null.

0
votes

If you only need to set up the grid once, this appears to be working for me.

Define an array with column data first. Then define the grid. Assume that the input parameter columnData is an array with meta-data in it.

function createGrid(columnData) {
    var columns = [{
        header: 'Period',
        dataIndex: 'period'
    }];
    for (var i = 0; i < columnData.length; ++i) {
        var column = {
            header: columnData[i].headerLabel,
            dataIndex: columnData[i].fieldName
        };
        columns[columns.length] = column; //or `columns.push(column);`
    }

    workGrid = Ext.create('Ext.grid.Panel', {
        title: 'Scheduled Driver Work',
        store: workStore,
        columns: columns,
        height: 600,
        renderTo: Ext.getBody()
    });
}
0
votes
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:"[email protected]"},
          {id:2,first:"Wilma",last:"Flintstone",email:"[email protected]"},
          {id:3,first:"Pebbles",last:"Flintstone",email:"[email protected]"},
          {id:4,first:"Barney",last:"Rubble",email:"[email protected]"},
          {id:5,first:"Betty",last:"Rubble",email:"[email protected]"},
          {id:6,first:"BamBam",last:"Rubble",email:"[email protected]"}],
    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);
});

please See http://www.sencha.com/forum/showthread.php?136362-Extjs-4-Dynamic-Model