Marc Savy
Marc Savy

Reputation: 450

How to insert association/child data into Ext.data.list as separate entries

I'm using ST2 and using MVC. I'm very new to ExtJS and Sencha, so am not au fair the best practices for many things - and on this issue I've hit a dead end despite research.

I'll use a toy example to illustrate my issue below, but essentially I have a relationship as follows (which all works correctly from an association perspective).

Business X  -- Location A
           |
            -- Location N

The Problem

I want to then populate the data into (for instance) an Ext.dataview.List, but to process it such that each location (i.e. child location) has its own separate entry in the table; not just a simple itemTpl formatting a single entry. However, at present I can't find any way to do that. Is it possible to hook into a List and format the data as I want, or should I be creating a new store? Ideally I want to make best use of the associations.

As a rough example, each entry would look like this, with some parent data and some child data:

    ---------------------------
    |Smith Co - 1 Smith Street|
    ---------------------------
    |Smith Co - 24 High Street|
    ---------------------------
    |Tea[...] - 12 Tea Leaf   |
    ---------------------------
    |Tea[...] - 3 Bis Kit     |
    ---------------------------

Example Code

Raw data

[
   {
      "id":1,
      "name":"Smith Co",
      "locations":[
         {
            "address":"1 Smith Street"
         },
         {
            "address":"24 High Street"
         }
      ]
   },
   {
      "id":2,
      "name":"Tea So Good",
      "locations":[
         {
            "address":"12 Tea Leaf"
         },
         {
            "address":"3 Bis Kit"
         }
      ]
   }
]

Location Model

Ext.define('Example.model.Location', {
    extend: 'Ext.data.Model',

    config: {
      fields: [
        { name: 'address', type: 'string' }
      ],
      proxy: { ... }, // Rest proxy that loads data as shown above.

      BelongsTo: 'Example.model.Company'
    }
});

Company Model

Ext.define('Example.model.Company', {
   extend: 'Ext.data.Model',

   config: {
     fields: [
       { name: 'id', type: 'int' },
       { name: 'name', type: 'string' }
     ],
     proxy: { ... }, // Rest proxy that loads data as shown above.

     hasMany: { model: 'Example.model.Location', name: 'locations' }

   }
});

Store

Ext.define('Example.store.Companies', {
    extend: 'Ext.data.Store',

    require: 'Example.model.Company',

    config: {
        model: 'Example.model.Company'
    } 
});

Controller

// (works correctly, relationships are traversable)
// Companies store is looked up and loaded in #launch()

View

Ext.define('Example.view.CompaniesList', {
    extend: 'Ext.List',
    xtype: 'companieslist', 

    config: {
        layout: 'fit',
        store: 'Businesses',
        itemTpl: [
            // Tpl is only to format inside each element
        ]
    }
});

Solution Edit (15th Sept 2013):

Solution

I used the solution @rixo suggested (and I had been hoping to avoid in the original question).

I created a separate store for the list, and loaded the data I need into it by using a load listener on the Companies store. This seems to be the most graceful solution available, although it means you may need to add extra logic in various places to ensure it remains satisfactorily synchronised.

By pushing the location objects themselves into the new store the associations remain intact (i.e. you can still do location.getCompany()).

Upvotes: 0

Views: 313

Answers (1)

rixo
rixo

Reputation: 25001

Yes, create another store for locations.

You may have tried a template like this:

itemTpl: [
    '{name}',
    '<tpl for="locations">',
        ', {address}',
    '</tpl>'
]

But that will indeed only display the information, it won't let you interact with each location as an individual list item.

You could get it working by hacking the view's doRefresh method, but that's just going against the lib's intention and other developer' expectations.

Maybe the problem is that you can get the data only in this format, that is with locations as children of companies, and you can't get the server to send you a flat list of companies. In that case, I think the most meaningful approach would be to customize a reader to flatten locations from companies, and feed a standalone location store. The extractData method seems a very promising start for that (see how the JSON reader uses it to implements its root property).

Upvotes: 1

Related Questions