Sencha Touch 2.3, hasMany association, and duplication of store entries

If you are working with Sencha Touch 2.3 (ST from this point onwards), then you may have developed a love/hate relationship with the platform like myself. Some aspects of the framework are great, whereas some others are sadly atrocious. The lack of coherent document, and the wide variety of conflicting information also does not help.

In a recent incident, I am using a hasMany association in the model and found a peculiar issue happening. To give you background of the issue, I have a model called Session which has a hasMany relationship with another model called Participant. Both models below:

The Session model:

    Ext.define('MyApp.model.Session', {
    extend: 'Ext.data.Model',

    requires: ['MyApp.model.Participant'],

    config: {

        idProperty: 'id',
        fields: [
            { name: 'id', type: 'int' },
            { name: 'number', type: 'string' },
            { name: 'time', type: 'string' },
            { name: 'date', type: 'string' },
            { name: 'day', type: 'string' },
            { name: 'title', type: 'string' },
            { name: 'abstract', type: 'string' },
            { name: 'track', type: 'string' },
            { name: 'room', type: 'string' },
            { name: 'building', type: 'string' }
        ],
        hasMany:
        {
            model: 'MyApp.model.Participant',
            name: 'participants',
            primaryKey: 'id',
            foreignKey: 'session_id',
            associationKey: 'participants'
        }
    }
});

The Participant model:

    Ext.define('MyApp.model.Participant', {
    extend: 'Ext.data.Model',

    config: {

        idProperty: 'id',

        fields: [
            { name: 'id', type: 'int' },
            { name: 'firstname', type: 'string' },
            { name: 'lastname', type: 'string' },
            { name: 'job_title', type: 'string' },
            { name: 'company', type: 'string' },
            { name: 'country', type: 'string' },
            { name: 'email', type: 'string' },
            { name: 'session_id', type: 'string' }
        ]
    }
});

The issue starts when you want to filter the Sessions store and show the changes immediately to the list that the store values are attached with.

The sessions store is as follows:

Ext.define('MyApp.store.Sessions', {
    extend: 'Ext.data.Store',

    config: {

        autoLoad: true,
        model: 'MyApp.model.Session',
        grouper: {
            groupFn: function (record) {
                return record.get('day') + " " + record.get('date');
            },
            sortProperty: 'id'
        },

        proxy: {
            type: 'ajax',
            url: 'resources/data/SessionsData.json',
            reader: {
                type: 'json',
                rootProperty: 'sessions'
            }
        }
    }
});
    

Suppose we want to do an anyMatch in the Sessions store. We have a search field introduced and here is the controller snippet to work with it.

        doSessionSearch: function(searchBox) {
            // Grab a reference to the Sessions store
            var mySessionsStore = Ext.getStore('Sessions');
            
            // Grab the current search string in the search box
            var searchValue = searchBox.getValue();
            
            // Generate a query out of the search string
            var query = new RegExp(searchValue, "i");
            
            // Clear all existing filters on the store
            mySessionsStore.clearFilter();
            
            // Apply the new filter
            mySessionsStore.filter('title', searchValue, true);
    }

However, this will result in your hasMany model duplicating the values. To avoid it, you will need to attach a listener to the calling store, which will clear values in the hasMany store. In our case, this means associating a listener to the Sessions store and clearing the entries for the Participants store.

The revised Sessions store will look like:

    Ext.define('MyApp.store.Sessions', {
    extend: 'Ext.data.Store',

    config: {

        autoLoad: true,
        model: 'MyApp.model.Session',
        grouper: {
            groupFn: function (record) {
                return record.get('day') + " " + record.get('date');
            },
            sortProperty: 'id'
        },

        listeners: {
            beforeload: function(operation) {
                for(var i=0; i<this.data.all.length; i++) {
                    if (this.data.all[i].participantsStore) {
                        this.data.all[i].participantsStore.removeAll();
                    }
                }
            }
        },

        proxy: {
            type: 'ajax',
            url: 'resources/data/SessionsData.json',
            reader: {
                type: 'json',
                rootProperty: 'sessions'
            }
        }
    }
});

I would have never reached this solution without the help provided by Martin Willitts in his original post over here.

1 comments On Sencha Touch 2.3, hasMany association, and duplication of store entries

  • I had a similar issue. I have 4 level model associations and my proxy on the root model, when loading records got duplicated … but with this same approach I managed to fix it. Thanks, nice post.

Leave a reply:

Your email address will not be published.

Site Footer

Sliding Sidebar

About Me

About Me

Strategy, Leadership, Innovation and Code Monkeyism

Social Profiles

Latest Tweets