Skip to content

Ext JS Grid Panels — Data Display, Editing, and Advanced Features

DodaTech Updated 2026-06-28 6 min read

In this tutorial, you will learn about Ext JS Grid Panels. We cover key concepts, practical examples, and best practices to help you master this topic.

Ext JS Grid panel is a feature-rich data table component that binds to Stores, supporting sorting, filtering, inline editing, grouping, row selection, pagination, and custom column rendering.

What You'll Learn

  • Configuring grid columns with renderers
  • Inline cell and row editing
  • Row selection models
  • Pagination and buffered rendering
  • Grid plugins and features

Why It Matters

Data tables are the most common UI pattern in enterprise applications. Ext JS Grid handles thousands of rows, complex column types, inline editing, and export — features that take months to build from scratch.

Real-World Use

An inventory management grid with 10,000+ products, editable quantity and price columns, real-time search, grouping by category, and pagination — all with smooth scrolling and sorting.

Grid Architecture

flowchart LR
    A[Grid Panel] --> B[Columns]
    A --> C[Store]
    A --> D[Selection Model]
    A --> E[Features]
    B --> F[Renderer]
    B --> G[Editor]
    C --> H[Data]
    E --> I[Grouping]
    E --> J[Pagination]
    E --> K[Filtering]
    style A fill:#e6f3ff,stroke:#4a90d9,stroke-width:2px

Basic Grid Configuration

Ext.create('Ext.grid.Panel', {
  title: 'Users',
  store: {
    fields: ['id', 'name', 'email', 'age', 'active'],
    data: [
      { id: 1, name: 'Alice', email: 'alice@example.com', age: 30, active: true },
      { id: 2, name: 'Bob', email: 'bob@example.com', age: 25, active: false },
      { id: 3, name: 'Charlie', email: 'charlie@example.com', age: 35, active: true }
    ]
  },
  columns: [
    { text: 'ID', dataIndex: 'id', width: 50 },
    { text: 'Name', dataIndex: 'name', flex: 1 },
    { text: 'Email', dataIndex: 'email', flex: 2 },
    { text: 'Age', dataIndex: 'age', width: 80, align: 'right' },
    { text: 'Active', dataIndex: 'active', width: 80, xtype: 'checkcolumn' }
  ],
  height: 350,
  width: 700,
  renderTo: Ext.getBody()
});

Expected output: A sortable, resizable grid with five columns. The Active column shows checkboxes. Columns with flex expand to fill available space.

Column Renderers

columns: [{
  text: 'Price',
  dataIndex: 'price',
  width: 100,
  align: 'right',
  renderer: function(value, metaData, record, rowIndex, colIndex, store) {
    // Format as currency
    return '$' + value.toFixed(2);
  }
}, {
  text: 'Status',
  dataIndex: 'status',
  width: 120,
  renderer: function(value) {
    var colors = {
      'active': 'green',
      'pending': 'orange',
      'inactive': 'red'
    };
    return '<span style="color:' + (colors[value] || 'gray') + '">' + value + '</span>';
  }
}, {
  text: 'Rating',
  dataIndex: 'rating',
  width: 150,
  renderer: function(value) {
    var stars = '';
    for (var i = 0; i < 5; i++) {
      stars += i < value ? '★' : '☆';
    }
    return stars;
  }
}]

Inline Editing

Ext.create('Ext.grid.Panel', {
  title: 'Editable Grid',
  store: myStore,
  columns: [{
    text: 'Name',
    dataIndex: 'name',
    flex: 1,
    editor: {
      xtype: 'textfield',
      allowBlank: false
    }
  }, {
    text: 'Price',
    dataIndex: 'price',
    width: 100,
    editor: {
      xtype: 'numberfield',
      minValue: 0,
      step: 0.01
    }
  }, {
    text: 'Category',
    dataIndex: 'category',
    width: 150,
    editor: {
      xtype: 'combobox',
      store: ['Electronics', 'Clothing', 'Food', 'Books'],
      queryMode: 'local'
    }
  }, {
    text: 'Active',
    dataIndex: 'active',
    xtype: 'checkcolumn'
  }],
  selType: 'rowmodel',
  plugins: {
    ptype: 'rowediting',
    clicksToEdit: 2
  },
  height: 400,
  renderTo: Ext.getBody()
});

Expected output: Double-clicking a cell opens an editor. Text fields, number fields, and combo boxes appear depending on the column configuration. Changes are saved to the Store.

Selection Models

// Row selection (default)
selType: 'rowmodel',
selModel: {
  mode: 'SINGLE' // or 'MULTI', 'SIMPLE'
}

// Cell selection
selType: 'cellmodel',

// Checkbox selection
selType: 'checkboxmodel',
selModel: {
  mode: 'MULTI',
  checkOnly: false
}

// Get selected records
var selected = grid.getSelectionModel().getSelection();
selected.forEach(function(record) {
  console.log(record.get('name'));
});

// Events
grid.on('selectionchange', function(selModel, selected) {
  console.log('Selected ' + selected.length + ' rows');
});

Pagination

Ext.create('Ext.grid.Panel', {
  store: {
    type: 'store',
    model: 'MyModel',
    autoLoad: true,
    pageSize: 25,
    proxy: {
      type: 'ajax',
      url: '/api/items',
      reader: { type: 'json', rootProperty: 'data', totalProperty: 'total' }
    }
  },
  columns: [/* ... */],
  bbar: {
    xtype: 'pagingtoolbar',
    displayInfo: true,
    displayMsg: 'Displaying {0} - {1} of {2}',
    emptyMsg: 'No data to display'
  },
  renderTo: Ext.getBody()
});

Grouping

Ext.create('Ext.grid.Panel', {
  store: {
    groupField: 'category',
    groupDir: 'ASC'
  },
  columns: [/* ... */],
  features: [{
    ftype: 'grouping',
    groupHeaderTpl: '{name} ({children.length})',
    collapsible: true,
    enableGroupingMenu: true
  }],
  renderTo: Ext.getBody()
});

Expected output: Rows are grouped by category with collapsible group headers showing item counts.

Grid Plugins

Ext.create('Ext.grid.Panel', {
  plugins: [
    { ptype: 'rowediting', clicksToEdit: 2 },
    { ptype: 'cellediting', clicksToEdit: 1 },
    { ptype: 'gridfilters', encode: false },
    { ptype: 'gridviewdragdrop', dragGroup: 'gridDD', dropGroup: 'gridDD' },
    { ptype: 'bufferedrenderer' }
  ],
  features: [
    { ftype: 'grouping' },
    { ftype: 'summary', dock: 'bottom' }
  ]
});

Common Mistakes

  1. Not setting a Store - A grid without a Store renders empty. Ensure the Store is defined and populated before creating the grid.

  2. Ignoring pageSize for server-side pagination - Without pageSize, the Store loads all records. Set pageSize and configure the proxy for server-side pagination.

  3. Using flex with fixed width columns - Flex columns share remaining space after fixed-width columns. If all columns have flex, the proportions are relative.

  4. Not handling the editor's complete event - After editing, the record is not automatically saved to the server. Listen for the edit event and call store.sync().

  5. Confusing store.load and store.reload - load() replaces all data. reload() requires that data was previously loaded. Use load() for initial load and load(params) for new queries.

Practice Questions

  1. How do you bind a Store to a Grid?
  2. What is the difference between cell editing and row editing?
  3. How do you format column values using a renderer?
  4. What is the purpose of the pagingtoolbar?
  5. How do you enable row selection and get selected records?

Challenge: Build an editable order grid with the following columns: product name (combo editor), quantity (number editor), price (read-only renderer), total (computed renderer), and status (combo editor). Add pagination, group by status, and save changes to the Store on edit.

FAQ

What is the difference between store.load() and store.reload()?

load() replaces the store's data. reload() re-requests the same data that was previously loaded. Both trigger a server request via the proxy.

Can I have multiple grids sharing the same Store?

Yes. Multiple grids can bind to the same Store. Changes in one grid (editing, sorting) affect all grids sharing that Store.

How do I export grid data to CSV or Excel?

Use the Ext.excel.Excel class or iterate the Store and build a CSV string manually. Ext JS does not have built-in export.

What is buffered rendering and when should I use it?

Buffered rendering creates DOM elements only for visible rows, enabling smooth scrolling with 100,000+ records. Use the bufferedrenderer plugin.

Can I use a tree store with a grid?

For hierarchical data, use Ext.tree.Panel instead of grid. Tree panels work similar to grids but support parent-child relationships.

Mini Project

Build a product inventory grid with: editable columns (price, quantity, status), grouping by category with collapsible groups, pagination (50 per page), checkbox selection, a summary row showing totals, and a toolbar button to save all changes.

What's Next

Grids display data. Learn how Ext JS Forms collect user input with field types, validation, and data binding to Models.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro