Dynamic Grid Panel for Ext JS

I am using Ext JS in my web application projects and I decided that it is time to give back to the community.

If you are developing a CRUD application and using grids to display data from your database you should define similar column models, fields, readers, stores etc. for your grids. It is not a big concern if it is not the first time you do the same things or you have your own components not to repeat yourself. But what if your database table needs a change in its structure? Let me guess… You change field and column model definitions in your grids and doing the same again and again even there are small changes.

Here is a small Ext JS component that I wrote:

Ext.ux.DynamicGridPanel = Ext.extend(Ext.grid.GridPanel, {
  initComponent: function(){
    /**
     * Default configuration options.
     *
     * You are free to change the values or add/remove options.
     * The important point is to define a data store with JsonReader
     * without configuration and columns with empty array. We are going
     * to setup our reader with the metaData information returned by the server.
     * See http://extjs.com/deploy/dev/docs/?class=Ext.data.JsonReader for more
     * information how to configure your JsonReader with metaData.
     *
     * A data store with remoteSort = true displays strange behaviours such as
     * not to display arrows when you sort the data and inconsistent ASC, DESC option.
     * Any suggestions are welcome
     */
    var config = {
      viewConfig: {forceFit: true},
      enableColLock: false,
      loadMask: true,
      border: false,
      stripeRows: true,
      ds: new Ext.data.Store({
		    url: this.storeUrl,
		    reader: new Ext.data.JsonReader()
		  }),
      columns: []
    };
    Ext.apply(this, config);
    Ext.apply(this.initialConfig, config);
    Ext.ux.DynamicGridPanel.superclass.initComponent.apply(this, arguments);
  },
  onRender: function(ct, position){
    this.colModel.defaultSortable = true;
    Ext.ux.DynamicGridPanel.superclass.onRender.call(this, ct, position);
    /**
     * Grid is not masked for the first data load.
     * We are masking it while store is loading data
     */
    this.el.mask('Loading...');
    this.store.on('load', function(){
      /**
       * Thats the magic! :)
       *
       * JSON data returned from server has the column definitions
       */
      if(typeof(this.store.reader.jsonData.columns) === 'object') {
	      var columns = [];
	      /**
	       * Adding RowNumberer or setting selection model as CheckboxSelectionModel
	       * We need to add them before other columns to display first
	       */
	      if(this.rowNumberer) { columns.push(new Ext.grid.RowNumberer()); }
	      if(this.checkboxSelModel) { columns.push(new Ext.grid.CheckboxSelectionModel()); }
        Ext.each(this.store.reader.jsonData.columns, function(column){
          columns.push(column);
        });
	      /**
	       * Setting column model configuration
	       */
	      this.getColumnModel().setConfig(columns);
      }
      /**
       * Unmasking grid
       */
      this.el.unmask();
    }, this);
    /**
     * And finally load the data from server!
     */
    this.store.load();
  }
});

How to use it?

new Ext.ux.DynamicGridPanel({
  id: 'my-grid',
  storeUrl: 'server/url/address/',
  rowNumberer: true,
  checkboxSelModel: true,
  sm: new Ext.grid.CheckboxSelectionModel(),
});

And here is the JSON which should be returned from server to dynamically create column and field definitions:

{
    "metaData": {
        "totalProperty": "total",
        "root": "records",
        "id": "id",
        "fields": [
            {
                "name": "id",
                "type": "int"
            },
            {
                "name": "name",
                "type": "string"
            }
        ]
    },
    "success": true,
    "total": 50,
    "records": [
        {
            "id": "1",
            "name": "AAA"
        },
        {
            "id": "2",
            "name": "BBB"
        }
    ],
    "columns": [
        {
            "header": "#",
            "dataIndex": "id"
        },
        {
            "header": "User",
            "dataIndex": "name"
        }
    ]
}

The code itself is somewhat self-explanatory but for newbie users learning center is a good start to understand how to extend Ext JS or simply understand how the framework works.

Suggestions and comments are welcome…

  • Sanjit

    Really Helpful.. But how do render a cell

  • Mike

    Awesome!  Exactly what I wanted.  Thanks for your hard work.

  • Tom

    This is how I got this to work with v3.4

    Ext.ux.DynamicGridPanel = Ext.extend(Ext.grid.EditorGridPanel, {
        id: ‘my-grid’,
        loadMask: true,
        border: false,
        stripeRows: true,
        initComponent: function() {
            Ext.applyIf(this, {
                ds: new Ext.data.Store({
                    url: this.storeUrl,
                    reader: new Ext.data.JsonReader()
                }),
                columns: []
            });
            Ext.ux.DynamicGridPanel.superclass.initComponent.call(this);
        },
        onRender: function(ct, position) {
            this.colModel.defaultSortable = true;
            RPS.Tools.DropDownEditorUi.superclass.onRender.call(this, ct, position);
            this.store.on(‘load’, function() {
                this.store.baseParams = {dropdown: ‘none’};
                /**
                 * Thats the magic!
                 *
                 * JSON data returned from server has the column definitions
                 */
                if (typeof(this.store.reader.jsonData.columns) === ‘object’) {
                    var columns = [];
                    /**
                     * Adding RowNumberer or setting selection model as CheckboxSelectionModel
                     * We need to add them before other columns to display first
                     */
                    if (this.rowNumberer) {
                        columns.push(new Ext.grid.RowNumberer());
                    }
                    if (this.checkboxSelModel) {
                        columns.push(new Ext.grid.CheckboxSelectionModel());
                    }
                    Ext.each(this.store.reader.jsonData.columns, function(column) {
                        columns.push(column);
                    });
                    /**
                     * Setting column model configuration
                     */
                    this.getColumnModel().setConfig(columns);
                }
            }, this);
            /**
             * And finally load the data from server!
             */
            this.store.load();
        }
    });

    Array setup for php:
            $metadata = array(‘metaData’ => array(‘totalProperty’ => ‘total’, ‘root’ => ‘records’, ‘id’ => ‘id’, ‘fields’ => array(array(‘name’ => ‘id’, ‘type’ => ‘int’), array(‘name’ => ‘name’, ‘type’ => ‘string’))));
            $columns = array(‘columns’ => array(array(‘header’ => ‘#’, ‘dataIndex’ => ‘id’, ‘editor’ => array(‘xtype’ => ‘textfield’)), array(‘header’ => ‘User’, ‘dataIndex’ => ‘name’)));
            $records = array(‘records’ => array(array(‘id’ => 1, ‘name’ => ‘AAA’), array(‘id’ => 2, ‘name’ => ‘BBB’)));
            $result = array_merge($metadata, array(‘success’ => 1, ‘total’ => 50), $records, $columns);
             echo json_encode($result);

    • Car_g12

      i try to use your code but it gives me this error: RPS is not defined can u help methanks

  • Pwelby

    Can you post an example of the PHP code you are using to pull out the JSON? I am having some trouble getting my PHP to generate the proper JSON metaData as output to be read by this process.

    • Anbarasanpajani

       Dynamic paging code has helped me. Pagination on this dynamic grid using bbar is not working. Any info would be highly appreciated.

  • Anonymous

    i can’t see the data in the grid. It’s blocked on ‘Loading…’

    • Booka

      luigimapu, did you solve your problem ? I’ve the same problem. It happens when i use “offline data”. With “online data”, it works !

      • Luigimapu

        no, i had changed my application. but what is your problem?

      • Onofabio

        What you want to say with “online data”

  • Luigimapu

    HI,
    i try the application, but i can’t see the data in the grid. The application is blocked on ‘LOADING…’, after show me the empty grid.
    Can you help me to resolve this problem?
    Thank you

  • http://www.facebook.com/profile.php?id=689450456 James Gough

    Anyone able to convert this to an XML based grid?

  • rose

    I can display grid header, but no data.
    any idea about this?

    Thanks a lot.

  • http://flexingflashing.blogspot.com Vijay Mareddy

    How do i use the LockingColumnModel within your example?

    colModel: new Ext.ux.grid.LockingColumnModel({}),

    view: new Ext.ux.grid.LockingGridView()

  • mjerom

    great,

    it’s been a realy usefull reading.
    however, i can’t find out how to paginate the result…

    any idea ?

  • Sedat

    Merhaba arkadaşlar ben yukarıdaki kodu bir türlüü çalıştıramadım sayfa boş gelmekte yani veri.json da veriyi bir türlü alamadı.Veri.json yukarıda verdiğin metadata bilgisi aynısı bulunmaktadır.Aynı dizinde bulunmaktadır.Ext.ux.DynamicGridPanel grid tanımlaması ise bir js dosyası olarak hazırladım görüyor.Sadece veri yüklemede sıkıntı bulunmaktadır.

    var grid =new Ext.ux.DynamicGridPanel({
    id: ‘my-grid’,
    storeUrl: ‘veri.json’,
    renderTo : ‘dene’,
    width : 400,
    height : 400,
    rowNumberer: true,
    checkboxSelModel: true,
    sm: new Ext.grid.CheckboxSelectionModel()});

    Yardımlarınız için şimdiden tşkler…

  • http://www.voksent.com raskri

    To work in IE I had to add:

    win.document.write(html);
    -> win.document.close();
    win.print();
    win.close();

    Using ext 3.1:
    Also noticed that grid.getTitle is not a function… so I used grid.title.

  • http://cppmayi.javaeye.com/ 刘亮

    非常感谢
    thanks very much

  • koucz

    Hello.

    How can I add a scrollbar to a grid.??

  • http://nattu4u.blogspot.com Nataraja

    Hi Erhan,

    I was following your post on the blog, and I am facing issues with this implementation of DynamicGridPanel. The date column is shown as [object Object] in the grid, however, the timestamp fields are shown appropriately. Kindly advise on what needs to be done in this case.

    Best Regards,
    Nataraja

  • Roger

    .. otherwise data won’t be shown on ext 3.0

    var grid = new Ext.ux.DynamicGridPanel({


    width: 600,
    height: 300,
    frame: true,
    title: ‘Framed’,
    iconCls: ‘icon-grid’
    });

  • Julian

    Is it possible to edit a value in the grid ??

    • Manil

      yes replace Ext.extend(Ext.grid.GridPanel by Ext.extend(Ext.grid.EditorGridPanel

  • Manil

    I want to refresh grid after loading data it’s possible ?

  • Pingback: blogs » Dynamic Grid Panel for Ext JS | ExtJS | Erhan is typing…

  • Trevor Orr

    Anyone get this working in ExtJS 3? Did you makes changes? If so can you post the changes you made?

  • Giovanni

    Hello, I’m trying your code with Ext 3.0 and is not working. Any tips ?

  • Cemal

    Ellerinize sağlık !

  • Diego L Espiñeira

    After struggling around for hours through the ExtJS source code, I found that in order to fix the strange sort behavior, you have to include in the sortInfo: { field: ‘blabla’, dir: ‘ASC’ } inside the metaData object in every response containing data.

  • JMS

    It seems to be a perfect solution .
    But , i am not abe to make it run .
    Could you add a simple zip file where we could get a working example of your solution.

    I have plenty tables and would like to avoid the formating definitions
    I use mssql2005, PHP5, IE6 , XP

    Thanks for any help there

  • zsw

    Thank you,it’s an useful inspirer

  • Jack

    Thanks for your solution. However, the latest Ext release is not working.

    I modified your code, instead of

    this.store.on(‘load’, function(){

    I use:

    this.store.on(‘metachange’, function() {

    It is working perfect now. One more thing, this.el.mask seems not required.

    Thanks

    • Georgio

      Thanks a lot for this tip !

      30 min i don’t understand why i can’t get my test to work !

    • Trevor Orr

      Is that the only change you made? I made the same change and it did not help.

  • Gerrat

    Brilliant!

    This is a great first step for a generic CRUD app I’m working on.
    I can’t believe I haven’t been able to find anything like this before.
    Thanks!

  • cxg28

    good

  • Tara

    Thank you for your very useful tutorial.
    I am tried you example, but the grid shows only one column. No column with the header “User” (dataIndex “name”)?

    • vagr

      how to load data not remote but local