Skip to content

Ext JS Components — Configuration, Lifecycle, and Customization

DodaTech Updated 2026-06-28 5 min read

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

Ext JS components are configurable objects with a defined lifecycle — init, render, destroy — that form the building blocks of every Ext JS application interface.

What You'll Learn

  • Component configuration and xtype system
  • Component lifecycle events (beforerender, render, afterrender, destroy)
  • Finding components with ComponentQuery
  • Creating custom components
  • Managing component state

Why It Matters

Every UI element in Ext JS is a component. Understanding their lifecycle, configuration, and how to find them is essential for building any Ext JS application.

Real-World Use

A dashboard where each widget (grid, chart, form) is a component. Widgets are added and removed dynamically, and the lifecycle ensures proper initialization and cleanup.

Component Lifecycle

flowchart LR
    A[Ext.create] --> B[beforeinit]
    B --> C[initComponent]
    C --> D[beforeRender]
    D --> E[Render]
    E --> F[afterRender]
    F --> G[Active State]
    G --> H[beforeDestroy]
    H --> I[Destroy]
    style C fill:#e6f3ff,stroke:#4a90d9,stroke-width:2px

Creating and Configuring Components

// Using Ext.create
var panel = Ext.create('Ext.panel.Panel', {
  title: 'My Panel',
  width: 400,
  height: 300,
  collapsible: true,
  html: 'Panel content',
  renderTo: Ext.getBody()
});

// Using xtype (lazy instantiation)
Ext.create('Ext.container.Viewport', {
  items: [{
    xtype: 'panel',
    title: 'Lazy Panel',
    html: 'This panel is created when the viewport renders'
  }]
});

// Updating configuration after creation
panel.setTitle('Updated Title');
panel.setWidth(500);
panel.collapse();

Expected output: The panel renders with a title, width, height, and collapsible feature. xtype defers creation until the container renders.

Component Lifecycle Events

Ext.define('MyApp.view.MyPanel', {
  extend: 'Ext.panel.Panel',
  title: 'Lifecycle Demo',

  initComponent: function() {
    console.log('1. initComponent');
    this.html = 'Lifecycle in action';
    this.callParent(); // Important: always call parent
  },

  listeners: {
    beforerender: function() {
      console.log('2. beforerender');
    },
    render: function() {
      console.log('3. render');
    },
    afterrender: function() {
      console.log('4. afterrender');
    },
    destroy: function() {
      console.log('5. destroy');
    }
  }
});

Expected output: The console logs show the order: initComponent, beforerender, render, afterrender, then destroy when the component is removed.

ComponentQuery

Find components anywhere in the hierarchy:

// Find by xtype
var allPanels = Ext.ComponentQuery.query('panel');
var grids = Ext.ComponentQuery.query('grid');

// Find by ID or itemId
var myPanel = Ext.ComponentQuery.query('#userGrid')[0];

// Find by attribute
var disabledButtons = Ext.ComponentQuery.query('button[disabled=true]');

// Find by class
var customWidgets = Ext.ComponentQuery.query('myapp-customwidget');

// Relative queries (from a container)
var container = Ext.getCmp('mainContainer');
var children = container.query('panel');
var firstChild = container.down('grid');
var parent = firstChild.up('viewport');

Expected output: ComponentQuery returns arrays of matching components. down() returns the first child match. up() traverses upward to find a parent.

Creating Custom Components

Ext.define('MyApp.view.InfoCard', {
  extend: 'Ext.panel.Panel',
  xtype: 'infocard',  // Custom xtype for lazy instantiation

  config: {
    iconCls: '',
    description: '',
    value: 0
  },

  initComponent: function() {
    Ext.apply(this, {
      cls: 'info-card',
      layout: 'fit',
      items: [{
        xtype: 'container',
        layout: 'vbox',
        padding: 15,
        items: [{
          xtype: 'component',
          cls: 'info-card-icon',
          html: '<span class="' + this.iconCls + '"></span>'
        }, {
          xtype: 'component',
          cls: 'info-card-value',
          html: '<h2>' + this.value + '</h2>'
        }, {
          xtype: 'component',
          cls: 'info-card-desc',
          html: '<p>' + this.description + '</p>'
        }]
      }]
    });

    this.callParent();
  },

  updateValue: function(newValue) {
    this.down('.info-card-value').update('<h2>' + newValue + '</h2>');
  }
});

// Usage
Ext.create('MyApp.view.InfoCard', {
  title: 'Revenue',
  iconCls: 'fa-dollar',
  description: 'Total revenue this quarter',
  value: 125000,
  renderTo: Ext.getBody()
});

Referencing Components

// By id (not recommended for reusable components)
var panel = Ext.getCmp('myPanelId');

// By itemId (recommended - scoped to parent)
var container = Ext.create('Ext.container.Container', {
  items: [{
    itemId: 'myButton',
    xtype: 'button',
    text: 'Click Me'
  }]
});
var btn = container.getComponent('myButton');

// By reference (Ext JS 5+)
Ext.define('MyApp.view.Main', {
  reference: 'mainView',
  items: [{
    xtype: 'button',
    reference: 'saveButton',  // Access via this.lookupReference('saveButton')
    text: 'Save'
  }]
});

Component State Management

Ext.define('MyApp.view.StatefulPanel', {
  extend: 'Ext.panel.Panel',
  stateful: true,
  stateId: 'myStatefulPanel',

  stateEvents: ['collapse', 'expand', 'resize'],

  getState: function() {
    return {
      collapsed: this.collapsed,
      width: this.getWidth(),
      height: this.getHeight(),
      x: this.getPosition()[0],
      y: this.getPosition()[1]
    };
  },

  applyState: function(state) {
    if (state.collapsed) this.collapse();
    this.setSize(state.width, state.height);
    this.setPosition(state.x, state.y);
  }
});

Common Mistakes

  1. Forgetting callParent() in initComponent - Failing to call this.callParent() breaks the component's initialization chain and causes unpredictable errors.

  2. Using Ext.getCmp() with reusable components - IDs must be unique. Use itemId with getComponent() or reference for reusable components.

  3. Modifying config after creation via direct property access - Use setter methods: setTitle(), setWidth(), not this.title = 'New'.

  4. Not destroying components - Call .destroy() when removing a component to trigger cleanup of event listeners and child components.

  5. Overriding the wrong lifecycle method - Override initComponent for one-time setup, afterRender for post-render operations, and beforeDestroy for cleanup.

Practice Questions

  1. What is the correct order of the component lifecycle events?
  2. How does xtype differ from Ext.create?
  3. What method is used to find components by xtype?
  4. Why should you call callParent() in initComponent?
  5. How do you access a child component by its itemId?

Challenge: Create a custom StatusBar component that extends Ext.toolbar.Toolbar. It should display the current time (updating every second), a connection status indicator, and the number of active users. Register it with a custom xtype.

FAQ

What is the difference between id and itemId?

id must be globally unique. itemId only needs to be unique within the parent container. itemId is preferred for reusable components.

Can I create a component without xtype?

Yes, use Ext.create('Ext.panel.Panel', config). xtype is a shorthand for lazy instantiation inside container items arrays.

How do I remove a component from its container?

Call container.remove(component) or component.destroy(). destroy() also removes from the parent.

What happens if I call .show() on an already-visible component?

Nothing - show() is idempotent. Similarly, hide() on a hidden component does nothing. Check .isVisible() first if needed.

Can I use HTML templates inside components?

Yes, use tpl and data configs on components. Ext JS supports XTemplate for advanced template rendering with loops and conditions.

Mini Project

Build a custom MetricWidget component that displays a title, value, trend arrow (up/down/flat), and a sparkline chart. Use it in a dashboard with four instances showing different metrics.

What's Next

Components live inside containers. Learn how containers and layouts arrange and manage child components in different visual arrangements.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro