Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Grouping in a Sencha Touch Store

DZone's Guide to

Grouping in a Sencha Touch Store

· Java Zone
Free Resource

Learn how to troubleshoot and diagnose some of the most common performance issues in Java today. Brought to you in partnership with AppDynamics.

In this article you will learn the approaches to performing grouping in a Sencha Touch Store. These are the topics that the article covers:

  • Using a Sencha Touch Store’s grouper config
  • Using the Store Class’s setGrouper method
  • Using the Store Class’s setGroupField method
  • Using the Store Class’s setGroupDir method

We will use a small application to try the different Sencha Touch Store grouping features available. The app will have the following directories:

stores-grouping-1

We need to include the Sencha Touch libraries in the index.html. My file looks like the screenshot below. Make sure that your file is pointing to the directory where you placed your copies of the Sencha Touch libraries.

stores-sorting-5

Creating the Model

Next we need to create a Sencha Touch Model for the records that we will place in the Store. In the Model directory, create the Product.js file and type the following model definition:

Ext.define('App.model.Product', {
    extend: 'Ext.data.Model',
    config: {
        idProperty: 'productCode',
        fields: [
            { name: 'productCode', type: 'string' },
            { name: 'productName', type: 'string' },
            { name: 'productLine', type: 'string' },
            { name: 'color', type: 'string' }
        ]
    }
});

We will declare this model in the models config of the app in the app.js file.

Ext.application({
    name: 'App',
    models: ['Product'],
    launch: function () {

    }
});

Creating the Store

We will also create the Products.js file in the Store directory. This is the definition of the store:

Ext.define('App.store.Products', {
    extend: 'Ext.data.Store',
    config: {
        model: 'App.model.Product',
        remoteSort:false,
        data: [
            { productCode: 'S10_1678', productName: '1969 Harley Davidson Ultimate Chopper', productLine: 'Motorcycles', color:'Red' },
            { productCode: 'S10_1949', productName: '1952 Alpine Renault 1300', productLine: 'Classic Cars', color: 'Silver' },
            { productCode: 'S10_2016', productName: '1996 Moto Guzzi 1100i', productLine: 'Motorcycles', color: 'Silver' },
            { productCode: 'S10_4698', productName: '2003 Harley-Davidson Eagle Drag Bike', productLine: 'Motorcycles', color: 'Silver' },
            { productCode: 'S12_1666', productName: '1958 Setra Bus', productLine: 'Trucks and Buses', color: 'Green' },
            { productCode: 'S10_4757', productName: '1972 Alfa Romeo GTA', productLine: 'Classic Cars', color: 'Red' },
            { productCode: 'S12_4473', productName: '1957 Chevy Pickup', productLine: 'Trucks and Buses', color: 'Brown' },
            { productCode: 'S18_1097', productName: '1940 Ford Pickup Truck', productLine: 'Trucks and Buses', color: 'Red' }
        ],
        grouper: {
            property: 'productLine',
            direction:'ASC'
        },
        sorters: [{
            property: 'productCode',
            direction: 'ASC'
        }]
    }
});

The grouper config is what we use to define how the Store’s records will be grouped. The property config of the Grouper object is used to group the Store’s records. The direction config is the direction used to sort the groups.

Other frequently used grouper configs are the groupFn and the sortProperty, not used in the code above. We can use the groupFn to customize how the groups are defined. Commonly, you would group records based on a property of the records. With groupFn you can provide a function that uses arbitrary criteria to define the groups. We will review a groupFn example later in this article.

The sortProperty config allows us to sort the groups by a property other than the groups themselves, whether the groups are defined by the property config or by the groupFn config.

Note that we have harcoded a few records using the data config. In a real-life app the Store would most likely pull these data from the server.

Let’s make sure to declare the store in the stores config of the application in the app.js file:

Ext.application({
    name: 'App',
    models: ['Product'],
    stores: ['Products'],
    launch: function () {

    }
});

Defining a Handler for the Store’s Load Event

With the model and store in place, we can look at the grouping features of the Store. In the app.js file, let’s first define a handler for the store’s load event The handler will allow us to perform grouping operations on the store and see the results in the browser’s console.

Ext.application({
    name: 'App',
    models: ['Product'],
    stores: ['Products'], 
    launch: function () {

        var productsStore = Ext.getStore('Products');

        productsStore.on({
            load: this.onStoreLoad
        });

        productsStore.load();


    },

    onStoreLoad: function (store, records) {

    }
});   

After reading this you might object that our Store is already loaded with hardcoded data and it is not necessary to reload it. True, but I want you to get familiar with this approach because in most real-life apps you will not have hardcoded data in the stores.

Using a Sencha Touch Store’s Grouper Config

Let’s first explore the grouper config, which is what we use at design time to define how the Store’s records will be grouped:

grouper: {
    property: 'productLine',
    direction:'ASC'
}

In order to see what happens to the Store’s records when we apply this config, we will add the following code in the onStoreLoad handler:

onStoreLoad: function (store, records) {

    var grouper = store.getGrouper();

    console.log('Records grouped by ' + grouper.getProperty() + ' ' + grouper.getDirection() + ':');
    store.each(function (record) {
        console.log('- ' + record.get(grouper.getProperty()) + ' - ' + record.get('productName'));
    });
}

In the handler we first invoke the store’s getGrouper method to acquire a reference to the Store’s grouper. Then, we log the grouper’s property and direction configs to the console by invoking their respective getter methods, getProperty and getDirection:

console.log('Records grouped by ' + grouper.getProperty() + ' ' + grouper.getDirection() + ':');

Last, we loop through the store’s records, logging the value of each record’s group and the value of the productName field:

store.each(function (record) {
        console.log('- ' + record.get(grouper.getProperty()) + ' - ' + record.get('productName'));
});

We can browse to the index.html file of the app in Google Chrome and see the log in the JavaScript Console:

stores-grouping-2

The SetGrouper Method of a Sencha Touch Store

The Store’s setGrouper method allows us to set the Store’s grouper at run time. To see it in action we will modify the app’s launch function as follows:

launch: function () {

        // Use the getStore function to get a reference to a store added via the stores config.
        var productsStore = Ext.getStore('Products');

        productsStore.on({
            load: this.onStoreLoad
        });

        productsStore.load();

        productsStore.setGrouper({
            property: 'color',
            direction: 'DESC'
        });

        // You have to reload for the new grouper to take effect.
        productsStore.load();

},

What we are doing here is switching the grouper from productLine ASC, which is what we set through the grouper config, to color DESC. After calling setGrouper we have to reload the Store so the grouper change takes effect.

Refreshing the index.html in Google Chrome should produce a second log that looks as depicted below.

stores-grouping-3

Using the SetGroupField and SetGroupDir Methods of a Sencha Touch Store

A couple of methods that you might want to try are setGroupField and setGroupDir. As their names indicate, they are setter methods for the Store’s groupField and groupDir configs. Inside the Store, these configs are mapped to the Store’s grouper’s property and direction configs.

Let’s use these methods in an example so you can see how they work. Back in the app’s launch function, we will make the following changes:

launch: function () {

    var productsStore = Ext.getStore('Products');

    productsStore.on({
        load: this.onStoreLoad
    });

    productsStore.load();

    productsStore.setGrouper({
        property: 'color',
        direction: 'DESC'
    });

    // You have to reload for the new grouper to take effect.
    productsStore.load();

    productsStore.setGroupField('productLine');
    productsStore.setGroupDir('DESC');
    productsStore.load();

    },
launch: function () {

    var productsStore = Ext.getStore('Products');

    productsStore.on({
        load: this.onStoreLoad
    });

    productsStore.load();

    productsStore.setGrouper({
        property: 'color',
        direction: 'DESC'
    });

    // You have to reload for the new grouper to take effect.
    productsStore.load();

    productsStore.setGroupField('productLine');
    productsStore.setGroupDir('DESC');
    productsStore.load();

    },

Pay attention to the last few lines, where we call the setGrouper method and use the groupFn to define a custom grouping function. In this simple example we use the first two letters of the productName field to define the groups. As I said earlier, you can use arbitrary logic here, based on the specific business rules of your application.

In order to see the results of using the custom grouper, we will make a small change to the onStoreLoad handler in the app.js file. First, we will define a loopsCounter variable right before the application’s definition:

var loopsCounter = 0;

Ext.application({

     // Details omitted for brevity.

});      

Then, we will modify the onStoreLoad handler like so:

onStoreLoad: function (store, records) {

    var grouper = store.getGrouper();

    if (loopsCounter < 3) {

        console.log('Records grouped by ' + grouper.getProperty() + ' ' + grouper.getDirection() + ':');
        store.each(function (record) {
            console.log('- ' + record.get(grouper.getProperty()) + ' - ' + record.get('productName'));
        });
    } else {
        console.log('Records grouped by first two chars of productName ' + grouper.getDirection() + ':');
        store.each(function (record) {
            console.log('- ' + record.get('productName'));
        });
    }

    loopsCounter++;
}

In the code above we use the loopsCounter variable to change the message that sent to the console. The reason for this change is that in the custom grouper example we do not use the Grouper’s property config and therefore we do not need to include this config’s value in the message that we send to the console.

Another refresh to the index.html file in Google Chrome should produce the results below in the Console.

stores-grouping-5

Download the Source Code

Download from GitHub: Sencha Touch Store Grouping tutorial by MiamiCoder

Want to Learn More About Mobile Web Apps Development?

MiamiCoder’s Sencha Touch and jQuery Mobile books will guide you, step by step, through the process of building Sencha Touch and jQuery Mobile applications. If you like to learn by doing, these books are for you.

Understand the needs and benefits around implementing the right monitoring solution for a growing containerized market. Brought to you in partnership with AppDynamics.

Topics:
java ,mobile ,tools & methods ,sencha touch

Published at DZone with permission of Jorge Ramon, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}