5

I want to make Nested list of shopping categories using data provided by server which looks something like this:

{
    "status":{"statusCode":15001},
    "data":[
        {"itemId":1, "name":"Men", "subCategories":[
            {"itemId":2, "name":"Clothes", "subCategories":[
                {"itemId":3, "name":"Formals", "leaf":true,"subCategories":[]},
                {"itemId":4, "name":"Casual", "leaf":true,"subCategories":[]},
                {"itemId":5, "name":"Sports", "leaf":true,"subCategories":[]}
            ]},
            {"itemId":6, "name":"Accessories", "subCategories":[
                {"itemId":7, "name":"Formals", "leaf":true,"subCategories":[]},
                {"itemId":8, "name":"Casual", "leaf":true,"subCategories":[]},
                {"itemId":9, "name":"Sports", "leaf":true,"subCategories":[]}
            ]}
        ]},
        {"itemId":10, "name":"Women", "subCategories":[
            {"itemId":11, "name":"Clothes", "subCategories":[
                {"itemId":12, "name":"Formals", "leaf":true,"subCategories":[]},
                {"itemId":13, "name":"Casual", "leaf":true,"subCategories":[]},
                {"itemId":14, "name":"Ethnic", "leaf":true,"subCategories":[]}
            ]},
            {"itemId":15, "name":"Shoes", "subCategories":[
                {"itemId":16, "name":"Hells", "leaf":true,"subCategories":[]},
                {"itemId":17, "name":"Wedges", "leaf":true,"subCategories":[]},
                {"itemId":18, "name":"Sports", "leaf":true,"subCategories":[]}
            ]}
        ]}
    ]
}

Since tree structure is wrapped in data element and children are wrapped in subCategories tag which is different from data so I wanted to pre-process this data such that it can be used by Nested List directly by making response like this:

{
    "categories":[
        {"itemId":1, "name":"Men", "categories":[
            {"itemId":2, "name":"Clothes", "categories":[
                {"itemId":3, "name":"Formals", "leaf":true,"categories":[]},
                {"itemId":4, "name":"Casual", "leaf":true,"categories":[]},
                {"itemId":5, "name":"Sports", "leaf":true,"categories":[]}
            ]},
            {"itemId":6, "name":"Accessories", "categories":[
                {"itemId":7, "name":"Formals", "leaf":true,"categories":[]},
                {"itemId":8, "name":"Casual", "leaf":true,"categories":[]},
                {"itemId":9, "name":"Sports", "leaf":true,"categories":[]}
            ]}
        ]},
        {"itemId":10, "name":"Women", "categories":[
            {"itemId":11, "name":"Clothes", "categories":[
                {"itemId":12, "name":"Formals", "leaf":true,"categories":[]},
                {"itemId":13, "name":"Casual", "leaf":true,"categories":[]},
                {"itemId":14, "name":"Ethnic", "leaf":true,"categories":[]}
            ]},
            {"itemId":15, "name":"Shoes", "categories":[
                {"itemId":16, "name":"Hells", "leaf":true,"categories":[]},
                {"itemId":17, "name":"Wedges", "leaf":true,"categories":[]},
                {"itemId":18, "name":"Sports", "leaf":true,"categories":[]}
            ]}
        ]}
    ]
}

For this I was overriding getResponseData of reader but this method never gets called and no records are loaded in store. What am I doing wrong?

Here is my store:

Ext.define('MyTabApp.store.CategoriesStore',{
    extend:'Ext.data.TreeStore',
    config:{
        model   : 'MyTabApp.model.Category',
        autoLoad: false,
        storeId : 'categoriesStore',
        proxy: {
            type: 'ajax',
            url: Properties.CONFIG_SERVICE_BASE_URL+'topnav/getall',
            reader: {
                type: 'json',
                getResponseData: function(response) {
                    console.log("in getResponseData"); // Never logged in console
                    var rText = response.responseText;
                    var processed = Helper.replaceAll("data","categories",rText);
                    processed = Helper.replaceAll("subCategories","categories",processed);
                    var respObj = Ext.JSON.decode(processed);
                    return respObj.categories;
                }
            }
        },
        listeners:{
            load: function( me, records, successful, operation, eOpts ){ 
                console.log("categories tree loaded");
                console.log(records); // This prints blank array
            }
        }
    }
});

and here is model:

Ext.define('MyTabApp.model.Category', {
    extend : 'Ext.data.Model',
    config : {
        idProperty  : 'itemId',
        fields      : [ 
           {name : 'itemId',type : 'int'}, 
           {name : 'name',type : 'string'}
        ]
    }
});

This is the list:

Ext.define('MyTabApp.view.CategoriesList', {
    extend: 'Ext.dataview.NestedList',
    alias : 'widget.categorieslist',
    config: {
        height              : '100%',
        title               : 'Categories',
        displayField        : 'name',
        useTitleAsBackText  : true,
        style               : 'background-color:#999 !important; font-size:75%',
        styleHtmlContent    : true,
        listConfig: {
            itemHeight: 47,
            itemTpl : '<div class="nestedlist-item"><div style="position:absolute; left:10px; top:10px; color:#222; font-size:130%">{name}</div></div>',
            height : "100%"
        }
    },
    initialize : function() {
        this.callParent();
        var me = this;

        var catStore = Ext.create('MyTabApp.store.CategoriesStore');
        catStore.load();
        me.setStore(catStore);
    }
});

What is best practice to process & format received data if it is not in the format we want and we don't have control over services?

ThinkFloyd
  • 4,981
  • 6
  • 36
  • 56
  • What would be the purpose of replacing keys in a javascript object ? Can't you cope with them ? – Titouan de Bailleul May 31 '13 at 11:00
  • I am trying to change `data` & `subCategories` strings to `categories` so that when it is parsed loaded in tree store my nested list would understand the data because all parent and child names are same. Please check my another question which is also related http://stackoverflow.com/questions/16854839/how-to-specify-rootproperty-for-nested-data-if-it-is-one-level-below – ThinkFloyd May 31 '13 at 11:43
  • basically I am getting data in some other format which is not like data used in [examples](http://docs.sencha.com/touch/2.1.1/#!/guide/nested_list) where `items` is name of arrays on all the levels. so I want to change my received data and make it like that before it is loaded in store. – ThinkFloyd May 31 '13 at 11:47
  • You could try to override to read function of the reader instead of the getReponseData – Titouan de Bailleul May 31 '13 at 12:22
  • Ok, I'll try that but if you can point me to some example that would be great – ThinkFloyd May 31 '13 at 12:36
  • I have tried overriding `read` method but like `getResponseData` it is also not getting called when data is loaded. Do I need to do something special to tell this method is overridden so execute this? Please check syntax of `getResponseData` method I have added earlier, I have added `read` method next to it. – ThinkFloyd May 31 '13 at 12:51
  • My bad! I did not realise that functions can only be overridden when you override the class and define method inside it. I have created separate reader class and added my `getResponseData` and `read` methods but now only `getResponseData` is getting called not `read` method but I can do filtering and load data into store. Bad news now is that I am stuck on this [issue](http://stackoverflow.com/questions/16854839/how-to-specify-rootproperty-for-nested-data-if-it-is-one-level-below) where after tap on any item nested list is again showing same list instead of children – ThinkFloyd May 31 '13 at 13:10

1 Answers1

0

I dont think you can attach getResponseData to reader's configuration. In past I have used the following approach.

  1. Create an override of Ext.data.reader.Json like below. But the downside is that this will be called for all your proxies using json reader. and then add YourApp.override.data.reader.Json in the requires section of your application.

    Ext.define('YourApp.override.data.reader.Json', { override: 'Ext.data.reader.Json', 'getResponseData': function(response) { // your implementation here }

  2. Alternatively you can make a Ext.Ajax.request and on success handler parse the data the way you want and then set the data in your store. You can also write this code in the "refresh" event or "beforeload" event of the store and return false to cancel the action

Abhi
  • 824
  • 9
  • 8