Results 1 to 5 of 5

Thread: DataView doesn't load belongsTo associations, so they can't be used in List's itemTpl

    Thank you for reporting this bug. We will make it our priority to review this report.
  1. #1
    Sencha User
    Join Date
    Aug 2011
    Posts
    5

    Default DataView doesn't load belongsTo associations, so they can't be used in List's itemTpl

    Sencha Touch version tested:
    • 1.1.0

    • only default ext-all.css


    Platform tested against:
    • Chrome
    • iOS4


    Description:
    • DataView doesn't fetch belongsTo associations to use in item templates. There's code in DataView:prepareAssociatedData() that pulls back hasMany, but it ignores belongsTo, so those items can't be used when templating a list.


    Test Case:


    Code:
    Ext.ns('MyApp');
     
    MyApp.Product = Ext.regModel('Product', {
        fields: [
            {name: 'id',      type: 'int'},
            {name: 'user_id', type: 'int'},
            {name: 'name',    type: 'string'}
        ],
    
    
        belongsTo: [
            {model: 'User', name: 'user'}
        ],
     
        proxy: {
            type: 'memory',
            id: 'user'
        }
    });
    
    
    MyApp.User = Ext.regModel('User', {
        fields: [
            {name: 'id',       type: 'int'},
            {name: 'name',     type: 'string'}
        ],
    
    
        associations: [
            {type: 'hasMany', model: 'Product', name: 'products'}
        ],
     
        proxy: {
            type: 'memory',
            id: 'product'
        }
    });
    
    
    Ext.regStore('User', {
        model: "User",
        data: [
            {
                id: 1,
                name: "nick"
            },
            {
                id: 2,
                name: "jim"
            }
        ]
        
    });
    
    
    Ext.regStore('Product', {
        model: "Product",
        data: [
            {
                id: 1,
                user_id: 1,
                name: "myProduct"
            },
            {
                id: 2,
                user_id: 1,
                name: "myProduct2"
            },
            {
                id: 3,
                user_id: 2,
                name: "myProduct3"
            },
            {
                id: 4,
                user_id: 2,
                name: "myProduct4"
            }
        ]
    });
    
    
    new Ext.Application({
        launch: function() {
            new Ext.Panel({
                fullscreen: true,
                items: [
                    {
                        id: 'productsList',
                        xtype: 'list',
                        store: Ext.getStore('Product'),
                        itemTpl: '{user.data.name} - {name}'
                    }
                ]
            });
        }
    });

    Steps to reproduce the problem:
    • Run provided test case


    The result that was expected:
    • Should display list of four products, each with correct names


    The result that occurs instead:
    • Javascript error prevents list from loading, because templating system complains that user.data is undefined.


    Possible Fix:
    • Hacked this together to fix the problem temporarily, but it's probably not optimal, as I don't understand the underlying architecture completely.
    Code:
    Ext.DataView.override({
        prepareAssociatedData: function(record, ids) {
            //we keep track of all of the internalIds of the models that we have loaded so far in here
            ids = ids || [];
            
            var associations     = record.associations.items,
                associationCount = associations.length,
                associationData  = {},
                associatedStore, associatedName, associatedRecords, associatedRecord,
                associatedRecordCount, association, internalId, i, j;
            
            for (i = 0; i < associationCount; i++) {
                association = associations[i];
    
    
                if (association.type == "belongsTo") {
                    var foreignKeyId = record.data[association.foreignKey];
                    var storeName = association.associatedName;
                    record.data[association.name] = Ext.getStore(storeName).getById(foreignKeyId);
                } else {
                    //this is the hasMany store filled with the associated data
                    associatedStore = record[association.storeName];
                
                    //we will use this to contain each associated record's data
                    associationData[association.name] = [];
                
                    //if it's loaded, put it into the association data
                    if (associatedStore && associatedStore.data.length > 0) {
                        associatedRecords = associatedStore.data.items;
                        associatedRecordCount = associatedRecords.length;
                
                        //now we're finally iterating over the records in the association. We do this recursively
                        for (j = 0; j < associatedRecordCount; j++) {
                            associatedRecord = associatedRecords[j];
                            internalId = associatedRecord.internalId;
                        
                            //when we load the associations for a specific model instance we add it to the set of loaded ids so that
                            //we don't load it twice. If we don't do this, we can fall into endless recursive loading failures.
                            if (ids.indexOf(internalId) == -1) {
                                ids.push(internalId);
                            
                                associationData[association.name][j] = associatedRecord.data;
                                Ext.apply(associationData[association.name][j], this.prepareAssociatedData(associatedRecord, ids));
                            }
                        }
                    }
                }
            }
            
            return associationData;
        }
    });

  2. #2
    Sencha User
    Join Date
    Sep 2011
    Posts
    125

    Default

    It is difficult to believe this was over look, considering how important it is. I mean who doesn't manage belongs to associations. Anyway... I think the below is a more optimal fix considering the relational data is present one the record. The only difference it look like between hasMany and belongsTo is that the association data is stored in a property called modelnameBelongsToInstance. So there isn't an apparent need to reload data using the store. I might be wrong though... I'm merely going of of what I see when I log/inspect the record data with some peaking under the hood.

    Code:
    Ext.DataView.override({
        prepareAssociatedData: function(record, ids) {
            //we keep track of all of the internalIds of the models that we have loaded so far in here
            ids = ids || [];
            
            var associations     = record.associations.items,
                associationCount = associations.length,
                associationData  = {},
                associatedStore, associatedName, associatedRecords, associatedRecord,
                associatedRecordCount, association, internalId, i, j;
            
            for (i = 0; i < associationCount; i++) {
                association = associations[i];
                
                if(association.type === 'belongsTo') {
                    
                    associatedRecord = record[association.associatedName + 'BelongsToInstance'];
                    
                    if(associatedRecord) {
                        associationData[association.name] = associatedRecord.data;
                        Ext.apply(associationData[association.name], this.prepareAssociatedData(associatedRecord, ids));
                    }
                    
                } else {
                
                    //this is the hasMany store filled with the associated data
                    associatedStore = record[association.storeName];
                    
                    //we will use this to contain each associated record's data
                    associationData[association.name] = [];
                    
                    //if it's loaded, put it into the association data
                    if (associatedStore && associatedStore.data.length > 0) {
                        associatedRecords = associatedStore.data.items;
                        associatedRecordCount = associatedRecords.length;
                    
                        //now we're finally iterating over the records in the association. We do this recursively
                        for (j = 0; j < associatedRecordCount; j++) {
                            associatedRecord = associatedRecords[j];
                            internalId = associatedRecord.internalId;
                            
                            //when we load the associations for a specific model instance we add it to the set of loaded ids so that
                            //we don't load it twice. If we don't do this, we can fall into endless recursive loading failures.
                            if (ids.indexOf(internalId) == -1) {
                                ids.push(internalId);
                                
                                associationData[association.name][j] = associatedRecord.data;
                                Ext.apply(associationData[association.name][j], this.prepareAssociatedData(associatedRecord, ids));
                            }
                        }
                    }
                
                }
                
            }
            
            return associationData;
        }
    });

  3. #3
    Sencha User
    Join Date
    Oct 2011
    Location
    Germany
    Posts
    146

    Exclamation fixed or not?

    Has this been fixed in 1.1.1 oder 2.0.0?

  4. #4
    Sencha User
    Join Date
    Sep 2011
    Posts
    125

    Default

    It isn't really a bug more so a feature enhancement. None the less, it has not been added in 1.1 or 2.0. You can see if you go look at the code.

  5. #5
    Sencha User
    Join Date
    Oct 2011
    Location
    Germany
    Posts
    146

    Default

    just another association bug:
    http://www.sencha.com/forum/showthre...ny-association

    I have the impression most devs are only progging tiny apps with sencha touch but no bigger databased ones with more than one table or relation...

    Maybe I will give up and come back in a year or two when Touch 3.1 is ready for prime time

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •