Latest Ext JS 7.8 is now available. Learn more

How to Work with Ext JS Models and Stores: Tutorial on Managing Data and State

April 28, 2024 1599 Views
Show

Ext JS is a popular JavaScript framework for creating robust enterprise-grade web and mobile applications. The framework offers a rich set of high-performance and fully-tested pre-built UI components (140+). These include menus, icons, buttons, carousels, sliders, and many more. Moreover, Ext JS offers one of the fastest JavaScript grids and supports a variety of charts and D3 visualizations, enabling you to build data-rich apps. It is also designed to be cross-browser compatible. This means the apps you create with Ext JS work seamlessly across modern browsers.

When creating web apps with Ext JS or any other framework, data management is crucial. It allows for efficient data storage, retrieval, manipulation, and management. In Ext JS applications, data models and stores are used to work with and manage data.

This tutorial will provide a thorough understanding of how to work with models and stores in the Ext JS framework to manage data and state.

Understanding Ext JS Models

Definition and Purpose

A model in Ext JS represents the structure of data entities in your app. It is basically an object that your app manages. For example, you can define a model for user names, emails, phone numbers, cars, products, or any other object you want to model. They allow you to define fields and their data types, providing a schema for your data.

Developers can utilize models to work with structured data in a consistent manner when creating Ext JS applications.

Components of Models

Key components of models include:

Fields

In Ext JS, we define models as a set of fields, including any arbitrary methods and properties related to the model.

Associations

Models can have associations with other Models. These associations define relationships between various models. We can define associations by fields/foreign keys, many-to-many/matrix, one-to-one, etc.

Validators

Ext JS provides built-in support for field validators within models. Validators allow us to define data validation rules on fields to ensure data integrity. In other words, validators help developers ensure that the data provided in a field is according to specific criteria, such as required fields, allowed values, minimum and maximum length, etc.

Model Configuration

Here’s an example of how you can create and configure models:

Defining a model:

Ext.define('User', {
    extend: 'Ext.data.Model',
    fields: [
        { name: 'name',     type: 'string' },
        { name: 'age',      type: 'int' },
        { name: 'phone',    type: 'string' },
        { name: 'gender',   type: 'string' },
        { name: 'username', type: 'string' },
        { name: 'alive',    type: 'boolean', defaultValue: true }
    ],
});

Adding validators:

validators: {
        age: 'presence',
        name: { type: 'length', min: 2 },
        gender: { type: 'inclusion', list: ['Male', 'Female'] },
        username: [
            { type: 'exclusion', list: ['Admin', 'Operator'] },
            { type: 'format', matcher: /([a-z]+)[0-9]{2,3}/i }
        ]
}

Setting up associations:

Let’s say we want to create associations between these two models:

Ext.define('User', {
    extend: 'Ext.data.Model',
    fields: [{
        name: 'id',
        type: 'int'
    }, 'name']
});

Ext.define('Order', {
    extend: 'Ext.data.Model',
    fields: [{
        name: 'id',
        type: 'int'
    }, {
        name: 'userId',
        type: 'int',
        reference: 'User'
    }]
});

Here is how we can define a keyless ‘hasMany’ association:

Ext.define('User', {
    extend: 'Ext.data.Model',
    fields: [{
        name: 'id',
        type: 'int'
    }, 'name'],
    hasMany: 'Order'
});

Ext.define('Order', {
    extend: 'Ext.data.Model',
    fields: [{
        name: 'id',
        type: 'int'
    }]
});

Working with Ext JS Stores

Store Overview

A Store in Sencha Ext JS is like a data repository or cache. It basically loads, stores, and manages data records or instances of a data model. In other words, an Ext JS Store contains a client-side cache of data model objects.

Stores load data through the Proxy (Ext.data.proxy.Proxy) class. Moreover, they provide helpful functions for filtering, querying, and sorting the model instances encapsulated within them.

Types of Stores 

There are multiple types of Stores available in Ext JS:

  • ArrayStore: Makes it easier to create stores from array data. In other words, we can use ArrayStore to directly define the data in our application code as an array of JavaScript objects.
  • JsonStore: Makes it easier to create stores/load data from a JSON data source
  • XmlStore: Makes it easier to create stores/load data from an XML data source

Loading and Managing Data

Here is an example of defining and loading data from a local store using the ArrayStore:

var store = Ext.create('Ext.data.ArrayStore', {
    // store configs
    storeId: 'myStore',
    // reader configs
    fields: [
       'company',
       {name: 'price', type: 'float'},
       {name: 'change', type: 'float'},
       {name: 'pctChange', type: 'float'},
       {name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}
    ]
});
// Define your data as an array of arrays
var myData = [
    ['3m Co',71.72,0.02,0.03,'9/1 12:00am'],
    ['Alcoa Inc',29.01,0.42,1.47,'9/1 12:00am'],
    ['Boeing Co.',75.43,0.53,0.71,'9/1 12:00am'],
    ['Hewlett-Packard Co.',36.53,-0.03,-0.08,'9/1 12:00am'],
    ['Wal-Mart Stores, Inc.',45.45,0.73,1.63,'9/1 12:00am']
];
// Load the data into the store
store.loadData(data);

Here is an example of defining and loading data in a JsonStore:

var store = new Ext.data.JsonStore({
    // store configs
    storeId: 'myStore',

    // Proxy configuration to load data from a server
    proxy: {
        type: 'ajax',
        url: 'get-images.php', // URL to fetch data from
        reader: {
            type: 'json',
            rootProperty: 'images' // Root property containing the array of data
        }
    },

    // Field definition for the data model
    fields: ['name', 'url', {name: 'size', type: 'float'}, {name: 'lastmod', type: 'date'}]
});

// Sample JSON data object
var jsonData = {
    images: [{
        name: 'Image one',
        url: '/GetImage.php?id=1',
        size: 46.5,
        lastmod: new Date(2007, 10, 29)
    }, {
        name: 'Image Two',
        url: '/GetImage.php?id=2',
        size: 43.2,
        lastmod: new Date(2007, 10, 30)
    }]
};

Filtering and Sorting:

var store = Ext.create('Ext.data.Store', {
    model: 'User', // Specifies the model associated with the store

    // Sorters configuration
    sorters: [{
        property: 'age', // Field to sort by
        direction: 'DESC' // Sorting direction (DESC for descending)
    }, {
        property: 'firstName',
        direction: 'ASC' // ASC for ascending
    }],

    // Filters configuration
    filters: [{
        property: 'firstName', // Field to filter by
        value: /Peter/ // Regular expression pattern to match
    }]
});

Check out more Ext JS tutorials here.

Data Binding and State Management

Ext JS MVVM architecture

Ext JS supports both MVC architecture and MVVM architecture. Both architectures leverage Ext JS Models, Stores, and Views. Data binding allows for automatic synchronization between Models, Stores, and Views (UI components that represent data visually).

How you use data binding in Ext JS depends on the architecture pattern you’re implementing. However, data binding generally connects the Model and View layers, ensuring seamless communication and synchronization between them. For example, in MVC architecture, data binding connects the Model and View layers. This means that the data from Models can be automatically displayed in UI components, such as forms, grids, charts, etc.

In MVVM architecture, we can use ViewModel Binding to bind Ext JS Views directly to ViewModels. This will enable the View to interact with data and operations exposed by the ViewModel. Ext JS also supports two-way data binding between the View and ViewModel for a responsive user interface. This means changes made in the View automatically update the ViewModel, and vice versa.

Managing Application State

Ext JS supports state management, enabling components to save and restore their state automatically. You can configure components with stateful: true, and their state will be persisted across page reloads or app restarts. You can store stateful information in Models or Stores and synchronize with the server as needed. For example, Models can represent user preferences, configuration settings, or other such aspects of the app state.

Stores can store and manage stateful data, such as filter criteria, user selections, or view configurations. By binding Views to Stores, changes in the application state are automatically reflected in the UI.

Advanced Techniques in Data Management

Data management in apps

Custom Data Readers and Writers

Readers in Ext JS are responsible for interpreting data (received as a response to an AJAX request) to be loaded in a Model or Store. In almost every instance, a Reader is used with a Ext.data.proxy.Proxy. You can configure a Reader using the Proxy’s reader configuration property.

Below is an example of a custom data reader. Here, we’ve used the ‘Ext.data.reader.Array’ class. This approach is helpful when dealing with array data that doesn’t follow the typical JSON or XML formats. It allows you to customize how the data is parsed and mapped to your models.

 Employee = Ext.define('Employee', {
     extend: 'Ext.data.Model',
     fields: [
         'id',
         // "mapping" only needed if an "id" field is present which
         // precludes using the ordinal position as the index.
         { name: 'name', mapping: 1 },
         { name: 'occupation', mapping: 2 }
     ]
 });

  var myReader = new Ext.data.reader.Array({
       model: 'Employee'
  }, Employee);

It will consume an Array like this:


 [ [1, 'Bill', 'Gardener'], [2, 'Ben', 'Horticulturalist'] ]

Data writers are used to write Models’ data to the server. It converts data from Models into a format suitable for sending to a server to save or update data. Ext JS provides built-in data writers for common data formats like JSON or XML. It also allows you to write custom data writers to handle certain requirements or server APIs.

Here is an example of a custom data writer:

Ext.define('MyApp.data.writer.CustomWriter', {
    extend: 'Ext.data.writer.Json', // Extend from the base JSON writer

    alias: 'writer.custom', // Alias for the custom writer

    // Override the getRecordData method to customize data formatting
    getRecordData: function(record, operation) {
        var data = this.callParent(arguments); // Call the parent method to get the default data

        // Custom logic to modify or add additional data fields
        data.customField = 'customValue';

        return data;
    }
});

Proxies for Remote Data

In Ext JS, Stores use proxies to handle the loading and saving of Model data, especially when working with remote data sources like servers or APIs. Proxies abstract the logic of data communication. Thus, they allow Models and Stores to interact with different data sources in a consistent manner.

Ext JS offers various types of proxies. Here we’ll discuss AJAX and REST Proxies:

AjaxProxy

AjaxProxy is the most common way of getting data into your app. It uses AJAX requests to load data from the server into a Store. Here is an example of a Store that has an Ajax Proxy:

Ext.define('User', {
    extend: 'Ext.data.Model',
    fields: ['id', 'name', 'email']
});

// The Store contains the AjaxProxy as an inline configuration
var store = Ext.create('Ext.data.Store', {
    model: 'User',
    proxy: {
        type: 'ajax',
        url: 'users.json'
    }
});

store.load();

REST Proxy

The Rest proxy is essentially a specialization of the AjaxProxy. It basically supports four actions/standard HTTP methods:

  • Create
  • Read
  • Update
  • Destroy

Here is an example of a model with an inline Rest proxy:

Ext.define('User', {
    extend: 'Ext.data.Model',
    fields: ['id', 'name', 'email'],

    proxy: {
        type: 'rest',
        url: '/users'
    }
});

You can now create a new User instance and save it through the Rest proxy. The Proxy will then send a POST request to ‘/users’:

var user = Ext.create('User', { name: 'Ed Spencer', email: '[email protected]' });
user.save(); // POST /users

If you have questions about Ext JS commercial licensing, training, or professional services, you can contact sales.

Best Practices and Performance Optimization

Performance optimization in Ext JS

Data Handling Best Practices

  • Define your Models so that they accurately represent the structure of your data entities.
  • Configure Stores appropriately
  • Follow consistent naming conventions for Models, Stores, fields, and methods across your app.
  • Implement error handling mechanisms to handle data loading errors efficiently.

Performance Optimization

  • Implement lazy loading to improve the app’s responsiveness.
  • Utilize batch processing to bundle multiple requests into a single batch.
  • Use virtual stores for large datasets to load data dynamically as needed.

Also Read: A Step-by-Step Guide To An Ext JS Tutorial For Beginners

Conclusion

Ext JS is a powerful Javascript framework for building robust web apps. It offers a diverse range of customizable UI widgets and also comes with additional helpful tools like Sencha Cmd, Sencha Touch, and Sencha Architect. The framework provides data models and stores to work with and manage data in your web apps. Models allow you to to define fields, validations and associations. A Store contains a client-side cache of data model objects.

In this tutorial, we’ve discussed in detail (with coding examples) how to work with data models and stores in Ext JS.

Build robust apps with Ext JS – get started now!

FAQs

How can I troubleshoot common data-related issues in Ext JS applications?

Troubleshooting common data-related issues involves identifying problems related to data loading, storing, and manipulation. These can include checking network requests, varying data configuration, etc. If you’re unable to troubleshoot or resolve issues, you can always contact Sencha support and get expert help.

What are the benefits of using custom data readers and writers?

Custom data readers and writers allow developers to:

  • Adapt data handling functionality to diverse requirements
  • Ensure compatibility
  • Enhance app performance

How can I handle complex data relationships using Ext JS Models?

You can utilize associates to handle complex data relationships between various models.