1
votes

This question has been asked twice before in on SO:

BUT neither of these questions have an actual answer, so I'm going to try again!

Let's say I have two models, User and Group. A user can be in many groups, and groups can contain many users. Here's the model code for User:

Ext.define('User', {
    extend: 'Ext.data.Model',
    alias: 'model.User',
    fields: [
        {name: 'username', type: 'string'},
        ...
    ],
    proxy: {
        // Omitted for brevity...
    },
});

And Group:

Ext.define('Group', {
    extend: 'Ext.data.Model',
    alias: 'model.Group',
    fields: [
        {name: 'name', type: 'string'},
        ...
    ],
    proxy: {
        // Omitted for brevity...
    },
});

Now, let's say I wanted a Grid which lists my groups, and allows me to double-click a group and edit which users are in that group in second grid.

Let's also say there's a lot of users per group, so I don't want to load all the associated users when I load the groups.

I want to be able get a store of users for a particular group, and give that to my grid, which will load data as needed (using the usual pagination that a grid does).

I see two potential approaches here. There may another better way, but I will outline what I've tried do so far below.

Intermediate model

  • Add another joining model
  • Add hasMany associations from User and Group to that model
  • Add belongsTo associations from my joining model back the way to User and Group.

Joining model code:

Ext.define('GroupUsers', {
    extend: 'Ext.data.Model',
    alias: 'model.GroupUsers',
    fields: [
        {name: 'group_id', type: 'int'},
        {name: 'user_id', type: 'int'},
    ],
    associations: [
        {type: 'belongsTo', model: 'User'},
        {type: 'belongsTo', model: 'Group'}
    ],
    ...
});

Association in Group:

associations: [
    {type: 'hasMany', model: 'GroupUsers', name: 'group_users'}
],

I will now be able to access a store of GroupUsers for a particular Group:

group.group_users()

The problem with this approach, is that I can't just bind a store of GroupUsers to my second grid, because I want to display things like the user's name. I could iterate the store's items, fetch each User object with getUser(), add them to another store, and use that for my Grid, but that results in a server request per item! Alternatively, I could use my store of GroupUsers directly, but then would need to do something with renderers and I still need to fetch each User individually.

Direct association

  • Associate User and Group directly with a hasMany association on each

Associations on Group:

associations: [
    {type: 'hasMany', model: 'User', name: 'users', foreignKey: '???'}
],

I can now get a store of actual User objects for a given group:

group.users()

Which would be great, except there's nothing for me to set the foreignKey of the association to. User can't have a group_id field, because a User can have many Groups!

1
The way I see it, let's assume we have the store information with the structure GroupId, GroupName, UserId, UserName (a combined store having all the records fetched using join). Let's say we have a grid to show the records which is grouped by GroupId and display a list of Groups, when expanded shows the list of users under that group. Now, assume a button click would rearrange the store and update the grid display to show a list of Users, when expanded shows the list of groups the user is under. The total logic behind this may be implemented with the store's filterBy and grouping grid featureMohammad Aftab Uddin
@MohammadAftabUddin thanks for your suggestion, but it doesn't really answer the question, I did say that I don't want to load all the data upfront.Jamie Cockburn
This is probably no solution for you, but just for the record, ManyToMany associations are supported in ExtJS 5.matt

1 Answers

3
votes

Maybe this is not the answer you look for, but this is how I would solve this issue :

I would not link the groups and the users with extjs store associations, but rather on the server side.

In the controller of your grid put something like this :

init: function(){
    this.control({
        'grid': {itemdblclick: this.onGridItemdblclick}
    })
},
onGridItemdblclick: function(grid, record){
    var group_id = record.getId(),
    usersStore = this.getStore('Users');
    usersStore.load({params: {group_id: group_id}});
    var win = Ext.widget('UsersGrid'); // adapt the code to your naming scheme
    win.show();
}

The request to load the Users store will be sent with an extra parameter group_id. On the server side, your can use this extra parameter to filter your users.