ExtJS 4: Understanding hasMany and belongsTo

incutonez picture incutonez · Oct 24, 2013 · Viewed 8.6k times · Source

I've been struggling to understand how to use hasMany and belongsTo for quite sometime. My understanding is hasMany is a 1:many relationship and belongsTo is a many:1 relationship--aside: so does that imply that if you have a hasMany relationship, a belongsTo is needed in its child model? I've read several articles on it:

Still a bit confused though. Let's say I have the following data:

var data = {
  "config": {
    "name": "blah",
    "id": 1,
    "someconfig": [{
        "name": "Services", "tabs": [{
            "id": 0, "name": "Details", "layout": "hbox"
          }, {
            "id": 1, "name": "Sources", "layout": "hbox"
          }, {
            "id": 2, "name": "Paths", "layout": "hbox"
          }, {
            "id": 3, "name": "Ports", "layout": "hbox"
          }, {
            "id": 4, "name": "Levels", "layout": "hbox"
          }, {
            "id": 5, "name": "Notes", "layout": "hbox"
          }]
      }, {
        "name": "Services2", "tabs": [{}]
      }]
  }
};

I would create a model for config:

Ext.define('Config', {
  extend: 'Ext.data.Model',
  fields: ['name'],
  hasMany: [{
    name: 'someconfig',
    model: 'Someconfig',
    associationKey: 'someconfig'
  }],
  proxy: {
    type: 'memory',
    data: data,
    reader: {
      type: 'json',
      root: 'config'
    }
  }
});

So Config can have many Someconfigs because in the data, someconfig is an array of objects. Here's the Someconfig model:

Ext.define('Someconfig', {
  extend: 'Ext.data.Model',
  fields: [
    'name'
  ],
  hasMany: [{
    name: 'tabs',
    model: 'Tabs',
    associationKey: 'tabs'
  }]
});

Ok, same deal. Someconfig can have many Tabs because in the data, tabs is an array of objects. Here's the Tabs model:

Ext.define('Tabs', {
  extend: 'Ext.data.Model',
  fields: [
    'id',
    'name',
    'layout'
  ],
  belongsTo: [{
    name: 'tabs',
    model: 'Someconfig',
    associationKey: 'tabs'
  }]
});

Now, belongsTo is in there because I was messing around with this property. Regardless, I can't access Tabs from Someconfig, but I can access Someconfig from Config. Take a look at this code:

Config.load(1, {
  success: function(record, operation) {
    console.log(record.get('name'));  // works
    console.log(record.someconfig().getCount());  // works, gives me 2
    console.log(record.someconfig().data.items[0].data);  // only prints out name and config_id
//      console.log(record.someconfig().tabs());  // doesn't exist
  }
});

jsFiddle: demo

What I want to know is, shouldn't I be able to access tabs() from someconfig(), or am I misunderstanding the relationships? If it's the former, how would I fix my code?

Cross-posted from Sencha forums.

Answer

overlordhammer picture overlordhammer · Oct 25, 2013

There are a few things wrong with your approach here:

  1. When you call the getter for a one-to-many relationship, you are actually retrieving a reference to a Store object that contains a set of related objects, so attempting to retrieve the relationship tabs for the store makes no sense.
  2. You must retrieve one element from the relationship store, and then get its related tabs by calling the tabs method that will return a Store Object containing a set of tabs for that specific instance.
  3. If you want to access to any of the related tabs you must again select a single object from that store, to transverse the whole relationship tree you should do something like this:
someconfig = record.someconfig().getAt(0);
sometab = someconfig.tabs().getAt(0);

Here's a modified version of your code that works. Hope it helps to solve your problem.