1. #1
    Touch Premium Member
    Join Date
    Sep 2011
    Posts
    7
    Vote Rating
    0
    remeis is on a distinguished road

      0  

    Default Ext.grid.GridPanel: adding/removing columns

    Ext.grid.GridPanel: adding/removing columns


    As I recognized by playing around with grids and reading many forum posts, adding and removing columns of a GridPanel is not an easy job.
    Edit: as scottmartin pointed out, using grid.reconfigure is easier and faster (see my post below for an example)

    Based on several posts and code written by Condor, which solves the problem in Ext 3.x (Adding removing fields and columns), I tried to override the GridPanel such that adding and removing works. My code for overriding the Model, Store and GridPanel can be found below.
    There might be, however, bugs and problems and I think solving them with the help of the community is the best way. If you have any ideas or suggestions or discover more bugs, please let us know

    Bugs/Problems:
    • none known at the moment

    I make sure the code is always up-to-date! In my case I'm using the MVC architecture, the code is used before the application definition.
    Code:
    //// MODEL ////
    Ext.require('Ext.data.Model', function() {
      Ext.data.Model.override({
        // returns the actual field definitions
        // and eventually excludes one field
        getFieldsInit: function(excludeName) {
          var tFields = new Array, j = 0;
          for (var i=0; i<this.fields.items.length; i++) {
            if (this.fields.items[i].name == excludeName) { j++; } else {
              tFields[i-j] = {
                name: this.fields.items[i].name,
                type: this.fields.items[i].type,
                defaultValue: this.fields.items[i].defaultValue,
              };
            }
          }
          return tFields;
        },
        // adds a new field given by an Ext.data.Field object
        addField: function(field) {
          var newFields = this.getFieldsInit();
          newFields.push(field);
          // override model
          Ext.define(this.$className, {
            extend: this.$className,
            fields: newFields
          });
        },
        // remove a field given by its name
        removeField: function(name) {
          var newFields = this.getFieldsInit(name);
          // override model
          Ext.define(this.$className, {
            extend: this.$className,
            fields: newFields
          });
        }
      });
    });
    
    //// STORE ////
    Ext.require('Ext.data.Store', function() {
      Ext.data.Store.override({
        // add a new field given by an Ext.data.Field object
        addField: function(field) {
          // modify model
          Ext.create(this.model).addField(field);
          // add data and insert new field into all records
          if (field.defaultValue == undefined) { field.defaultValue = ''; }
          this.each(function(record) {
            record.fields.add(Ext.create("Ext.data.Field", field));
            record.set(field.name, field.defaultValue);
            record.commit();
          });
        },
        // remove a field given by its name
        removeField: function(name) {
          // modify model
          Ext.create(this.model).removeField(name);
          // remove data and field from all records
          this.each(function(record) {
            record.fields.removeAt(record.fields.findIndex('name', name));
            delete record.data[name];
          });
        }
      });
    });
    
    //// GRIDPANEL ////
    Ext.require('Ext.grid.GridPanel', function() {
      Ext.grid.GridPanel.override({
        // update the plugins
        updatePlugins: function() {
          // to get the plugins running they have to be re-created
          var newPlugins = new Array;
          for (var i=0; i<this.initialConfig.plugins.length; i++) {
            newPlugins.push(Ext.create(this.plugins[i].$className,
              this.initialConfig.plugins[i]
            ));
            newPlugins[i].init(this);
          }
          this.plugins = newPlugins;
        },
        // add a new column to the grid:
        //   field    - may be either a new field to be inserted into the
        //              connected store (Ext.data.field) or a column object
        //              (Ext.grid.column.Column). In the latter case a
        //              field will be created by the columns dataIndex,
        //              thus no column object has to be given
        //   column   - a new column object to be added to the grid
        //              (Ext.grid.column.Column) (optional)
        //   colIndex - the column number where the new column has to be
        //              added (optional, default is to add it to the end)
        addColumn: function(field, column, colIndex) {
          // check if column definition is given
          if (! column) {
            // if not create from given field
            if (field.dataIndex) {
              column = field;
              field = { name: field.dataIndex };
            }
            else { column = field.name || field; }
          }
          // add field to store
          this.store.addField(field);
          // add column to grid
          this.headerCt.insert(colIndex || this.columns.length, column);
          // update plugins
          this.updatePlugins();
          // refresh the gried view
          this.getView().refresh();
        },
        // remove a column given by the store's field name. If the colIndex is not
        // given, the column with matching dataIndex will be removed
        removeColumn: function(name, colIndex){
          // remove field from store
          this.store.removeField(name);
          // remove column from grid
          if (typeof colIndex != 'number') { colIndex = this.headerCt.items.findIndex('dataIndex', name); }
          if (colIndex >= 0) { this.headerCt.remove(colIndex); }
          // update plugins
          this.updatePlugins();
          // refresh the gried view
          this.getView().refresh();
        }
      });
    });

    Some Examples
    Code:
    // add a column given by a column object only to the end of the grid
    myGrid.addColumn({
      dataIndex: 'Amount'
    });
    
    // add a column to a grid given by a new store field and a more complex column object
    myGrid.addColumn(
      { // new field for the store
        name: 'amount01',
        type: 'float',
        defaultValue: 0
      },
      { // new column object for the grid
        dataIndex: 'Amount January',
        editor: {
          xtype: 'textfield'
        }
      },
      2 // add to position 2
    );
    
    // remove a column given by the store's field name
    myGrid.removeColumn('Amount');
    
    // remove the column at a specific position and a specific store's field name
    myGrid.removeColumn('amount01', 2);
    Last edited by remeis; 10 May 2012 at 3:16 AM. Reason: note on grid.reconfigure added

  2. #2
    Sencha - Support Team scottmartin's Avatar
    Join Date
    Jul 2010
    Location
    Houston, Tx
    Posts
    9,010
    Vote Rating
    460
    scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future

      0  

    Default


    It is much easier and faster to create custom column arrays and use grid.reconfigure to change the columns.

    Have you given this a try?

    Regards,
    Scott.

  3. #3
    Touch Premium Member
    Join Date
    Sep 2011
    Posts
    7
    Vote Rating
    0
    remeis is on a distinguished road

      0  

    Default


    You're right, scottmartin. I once gave grid.reconifgure a try, but to be honest I was confused what to do and forgot about that function. Now that I've wrote the stuff above it is clear to me.
    However, do I understand it correctly, that with using grid.reconfigure the model of the store is not updated? At least, I had to avoid using a model. Here is the code where I played with grid.reconfigure:
    Code:
    // define the initial columns of the grid
    var myCols = [
      {
        header: 'col 1',
        dataIndex: 'col1',
        editor: {
          xtype: 'textfield'
        }
      }
    ];
    // define the initial fields of the store
    var myFields = [
      {
        name: 'col1',
        type: 'string',
        defaultValue: ''
      }
    ];
    // create the grid
    var gp = new Ext.grid.Panel({
      // define the store with the fields above
      store: Ext.create('Ext.data.Store', {
        fields: myFields,
        proxy: { type: 'memory' }
      }),
      // define the columns with the ones above
      columns: myCols,
      selModel: {
        selType: 'cellmodel'
      },
      plugins: [{
        ptype: 'cellediting',
        clicksToEdit: 1
      }],
      tbar: [
        {
          xtype: 'button',
          text: 'add col',
          // function to add one column
          handler: function() {
            var i = myFields.length + 1;
            // append a new field to the field array
            myFields.push({
              name: 'col' + i,
              type: 'string',
              defaultValue: ''
            });
            // append a new column to the column array
            myCols.push({
              header: 'col ' + i,
              dataIndex: 'col' + i,
              editor: {
                xtype: 'textfield'
              }
            });
            var grid = this.ownerCt.ownerCt;
            // retrieve the data which is already in the store
            var myData = grid.getStore().data.items;
            // modify the grid (adds the column and the field, overriding the existing store)
            grid.reconfigure(
              Ext.create('Ext.data.Store', {
                fields: myFields,
                proxy: { type: 'memory' }
              }),
              myCols
            );
            // add the previous data into the new store
            grid.getStore().loadData(myData);
          }
        },
        {
          xtype: 'button',
          text: 'add row',
          // function to add one row
          handler: function() {
            var grid = this.ownerCt.ownerCt;
            var store = grid.getStore();
            store.insert(store.data.getCount(), Ext.create(store.model));
          }
        }
      ]
    });
    One thing that is still ugly is, that if I already have one or more rows and add a new col, the data of the new cells is something like
    Code:
    <div id="ext-gen1181" unselectable="on" class="x-grid-cell-inner x-unselectable" style="; text-align: left;">&nbsp;</div>
    If I do not add the existing data to the new store (using store.loadData) then this problem does not arise, of course, because the grid is empty. But this is not what one usually wants.

  4. #4
    Sencha - Support Team scottmartin's Avatar
    Join Date
    Jul 2010
    Location
    Houston, Tx
    Posts
    9,010
    Vote Rating
    460
    scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future

      0  

    Default


    Typically I define the store with all the fields then define the column arrays and reconfigure as needed instead of creating a new store. You can also concat column arrays to make it easier to have common fields:

    Code:
    var store = Ext.create('Ext.data.Store', {
    ..
    });
    
    var myCols1 = [ { .. } ];
    var myCols2 = [ { .. } ];
    
    grid.reconfigure(store,myCols2);
    Regards,
    Scott.

Thread Participants: 1

Tags for this Thread