1. #1
    Sencha User
    Join Date
    Dec 2008
    Posts
    17
    Answers
    1
    Vote Rating
    0
    adube is on a distinguished road

      0  

    Question Answered: Model association not working

    Answered: Model association not working


    Hi,

    I'm new with Ext JS 4.0. After reading the Data and MVC documentation, I'm now trying it out for the first time. I'm having currently having issues with the model association.

    My use-case is as follow : a Config hasMany Resources, a Resource belongsTo a Config. I currently use a static JSON of what I expect my server to output for a "getConfig" request, which should return a single "config" element with a "resources" array parameter. My problem is that I expect the config.resources() method to exists and it doesn't or have a records[0].data.resources parameter set but it's not.

    Here's a complete and very simple live demo demonstrating my issue. I have a view.resource.Grid object I expect to have the 2 resources elements read from the JSON file displayed, but they're not.

    http://dev8.mapgears.com/extjs4-association/

    What am I doing wrong ?

    Many thanks,

    Alexandre

  2. Thanks to you börn, I finally got it working. It was a combination of the two ways actually.

    On grid 'afterrender', I can get a hold on the grid instance, but the configStore hasn't been loaded yet at that point, thus resulting in not having the configStore.records[0].data.resourcesStore created. That means I still need to listen to the configStore 'load' event. By keeping the grid instance as a private property of the controller, I'm able to use it in the store 'load' callback.

    I updated the online sample. Here's how it looks now :

    controller.Config portion
    Code:
    ...
        init: function() {
            console.log('Initialized Configs Controller!');
            var me = this;
    
    
            me.getConfigStore().on({
                scope: me,
                load : me.onConfigStoreLoad
            });
    
    
            this.control({
                'resourcegrid': {
                    'afterrender': this.onResourceGridAfterRender
                }
            }, this);
        },
    
    
        onLaunch: function() {
            var foo = "bar";
        },
    
    
        onResourceGridAfterRender: function(grid, options) {
            console.log('resourcegrid afterrender fired!');
            this.resourceGrid = grid;
        },
    
    
        onConfigStoreLoad: function(store, records) {
            console.log('Config store loaded with '+records.length+' record(s).');
    
    
            if (records.length && records[0] && records[0].resourcesStore &&
                this.resourceGrid
            ) {
                console.log(
                    'Config store has a resourcesStore with '+
                    records[0].resourcesStore.data.length +
                    ' record(s), reconfiguring resourceGrid!'
                );
                this.resourceGrid.reconfigure(records[0].resourcesStore)
            }
        }
    ...

    Console log

    Code:
    Initialized Configs Controller!
    initComponent GeoPrisma.view.resource.Grid
    resourcegrid afterrender fired!
    Config store loaded with 1 record(s).
    Config store has a resourcesStore with 2 record(s), reconfiguring resourceGrid!

  3. #2
    Sencha - Senior Forum Manager mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    36,801
    Answers
    3467
    Vote Rating
    834
    mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute

      0  

    Default


    Can you post your model here?
    Mitchell Simoens @SenchaMitch
    Sencha Inc, Senior Forum Manager
    ________________
    Check out my GitHub, lots of nice things for Ext JS 4 and Sencha Touch 2
    https://github.com/mitchellsimoens

    Think my support is good? Get more personalized support via a support subscription. https://www.sencha.com/store/

    Need more help with your app? Hire Sencha Services services@sencha.com

    Want to learn Sencha Touch 2? Check out Sencha Touch in Action that is in print!

    When posting code, please use BBCode's CODE tags.

  4. #3
    Sencha User
    Join Date
    Dec 2008
    Posts
    17
    Answers
    1
    Vote Rating
    0
    adube is on a distinguished road

      0  

    Default


    Sure. Here goes :

    Json

    Code:
    {
        "success": true,
        "config": {
            "id": 1,
            "resources": [{
                "name": "R_OSM",
                "title": "OpenStreetMap",
                "abstract": "This is the OpenStreetMap resource"
            }, {
                "name": "R_Countries_Population",
                "title": "Countries Population",
                "abstract": "Custom countries population points"
            }]
        }
    }
    Models
    Code:
    Ext.define('GeoPrisma.model.Config', {
        extend: 'Ext.data.Model',    requires: [
            'GeoPrisma.model.Resource',
            'Ext.data.HasManyAssociation',
            'Ext.data.BelongsToAssociation'
        ],
        fields: ["id"],
     
       //hasMany: {model: "Resource", name: "resources"}
        hasMany: {model: "GeoPrisma.model.Resource", name: "resources"}}
    );
    Code:
    Ext.define('GeoPrisma.model.Resource', {
        extend: 'Ext.data.Model',
        fields: ["config_id", "name", "title", "abstract"],
            //belongsTo: 'Config'
        belongsTo: 'GeoPrisma.model.Config'
    });
    Stores
    Code:
    Ext.define('GeoPrisma.store.Config', {
        extend: 'Ext.data.Store',
        model: "GeoPrisma.model.Config",
        autoLoad: true,
        proxy: {
            type: 'ajax',
            url: 'data/config.json',
            reader: {
                type: 'json',
                root: 'config',
                successProperty: 'success'
            }
        }
    });
    Code:
    Ext.define('GeoPrisma.store.Resources', {
        extend: 'Ext.data.Store',
        model: "GeoPrisma.model.Resource"
    });

    view.resource.Grid
    ​, which is empty
    Code:
    Ext.define('GeoPrisma.view.resource.Grid' ,{
        extend: 'Ext.grid.Panel',
        alias : 'widget.resourcegrid',
        title : 'Resources Grid',
        //store: 'GeoPrisma.store.Resources',
        store: 'Resources',
        width: 400,
        height: 200,
        border: true,
        initComponent: function() {
            console.log('initComponent GeoPrisma.view.resource.Grid');
            this.columns = [
                {header: 'Name',  dataIndex: 'name',  flex: 1},
                {header: 'Title', dataIndex: 'title', flex: 1},
                {header: 'Abstract', dataIndex: 'abstract', flex: 1}
            ];
            this.callParent(arguments);
            var foo = "bar";
        }
    });
    Thanks a lot,

    Alexandre

  5. #4
    Sencha User
    Join Date
    Feb 2010
    Posts
    125
    Answers
    7
    Vote Rating
    3
    börn is on a distinguished road

      0  

    Default


    Your grid should have it's store config set to yourLoadedRecord.resources()... maybe there is a timing problem.. try to play with the loaded model and it's associations in the console. You may consider using reconfigure in your grid after your model is successfully loaded.

  6. #5
    Sencha User
    Join Date
    Dec 2008
    Posts
    17
    Answers
    1
    Vote Rating
    0
    adube is on a distinguished road

      0  

    Default


    Thanks for your reply.

    Okay, let me know if I get this right. When setting
    Code:
    store: "Resources"
    inside the view.resource.Grid, it creates a store.Resources but it's not the same instance as the store.Resources the Config record has.

    Alexandre

  7. #6
    Sencha User
    Join Date
    Dec 2008
    Posts
    17
    Answers
    1
    Vote Rating
    0
    adube is on a distinguished road

      0  

    Default


    Hi,

    I made some modifications following that logic. Now I can see the resourcesStore property inside the config record and it has 2 resource records.

    Next step, bind this store to my grid. In the controller, I get the grid using the getResourceGridView() then expect to be able to use the reconfigure() method, but the object returned is not an instance of a Ext.grid.Panel.

    What is the correct way to bind the store to the grid and how to get it ?

    I updated the online sample at http://dev8.mapgears.com/extjs4-association/. Here's also a copy of the controller I use and the console log.

    Thanks,

    Alexandre

    ​Controller
    Code:
    Ext.define('GeoPrisma.controller.Config', {
        extend: 'Ext.app.Controller',
    
    
        stores: [
            "Config",
            "Resources"
        ],
    
    
        models: [
            "Config"//,
            //"Resource"
        ],
    
    
        views: [
            'resource.Grid'
        ],
    
    
        init: function() {
            console.log('Initialized Configs Controller!');
            var me = this;
    
    
            me.getConfigStore().on({
                scope: me,
                load : me.onConfigStoreLoad
            });
        },
    
    
        onLaunch: function() {
            var foo = "bar";
        },
    
    
        onConfigStoreLoad: function(store, records) {
            var foo = "bar";
            console.log('Config store loaded with '+records.length+' record(s).');
    
    
            if (records.length && records[0] && records[0].resourcesStore) {
                console.log(
                    'Config store has a resourcesStore with '+
                    records[0].resourcesStore.data.length +
                    ' record(s)'
                );
    
    
                // check if resourceGridView is a Ext.grid.Panel
                var grid = this.getResourceGridView();
                var isGrid = (grid instanceof Ext.grid.Panel);
    
    
                // console log for isGrid
                var msg = [];
                msg.push(grid.getName() + ' is ');
                !isGrid && msg.push('not ');
                msg.push('an instance of Ext.grid.Panel');
                console.log(msg.join(""));
    
    
                // reconfigure if isGrid
                isGrid && grid.reconfigure(records[0].resourcesStore)
            }
        }
    });

    Console Log

    Code:
    Initialized Configs Controller!
    initComponent GeoPrisma.view.resource.Grid
    Config store loaded with 1 record(s)
    Config store has a resourcesStore with 2 record(s)
    GeoPrisma.view.resource.Grid is not an instance of Ext.grid.Panel

  8. #7
    Sencha User
    Join Date
    Feb 2010
    Posts
    125
    Answers
    7
    Vote Rating
    3
    börn is on a distinguished road

      0  

    Default


    I think the store load is to early for calling reconfigure. The deal with reconfigure is to put a new store and new columns to a grid, which is allready there. If you are in your init-processing of the controller this isn't the case. I configured a onRender Function in my controller where i call the grid with reconfigure.. i think your
    this.getResourceGridView() call only gets you a pointer to the constructor of your grid-panel so this wouldn't be a reference to the view and therefor not an instanceof a grid.

    I suggest something like this in your controller:

    Code:
    ...
    
    init: function() {
    
    
      this.control('yourgridxtype': {
                                       'afterrender' : this.reconfigureView
                                    }
                   ,this);
    
    
    },
    
    reconfigureView: function(grid) {
    
      grid.reconfigure(this.getStore());   //don't know wether you have to deal with the columns... i do, 2nd parameter
    
    }


    But this is how i do that - and this is mainly because I'm also configuring my grid with some kind of metadata sent by the server to adjust columsn and stuff. If you have something more ungeneric you should be able to achieve your goals in a more simple way, only by adding the store of the model to the grid maybe in your init processing. And then overwrite a initComponent function in your grid-view and setting the given store of the model in it.

  9. #8
    Sencha User
    Join Date
    Dec 2008
    Posts
    17
    Answers
    1
    Vote Rating
    0
    adube is on a distinguished road

      0  

    Default


    Thanks to you börn, I finally got it working. It was a combination of the two ways actually.

    On grid 'afterrender', I can get a hold on the grid instance, but the configStore hasn't been loaded yet at that point, thus resulting in not having the configStore.records[0].data.resourcesStore created. That means I still need to listen to the configStore 'load' event. By keeping the grid instance as a private property of the controller, I'm able to use it in the store 'load' callback.

    I updated the online sample. Here's how it looks now :

    controller.Config portion
    Code:
    ...
        init: function() {
            console.log('Initialized Configs Controller!');
            var me = this;
    
    
            me.getConfigStore().on({
                scope: me,
                load : me.onConfigStoreLoad
            });
    
    
            this.control({
                'resourcegrid': {
                    'afterrender': this.onResourceGridAfterRender
                }
            }, this);
        },
    
    
        onLaunch: function() {
            var foo = "bar";
        },
    
    
        onResourceGridAfterRender: function(grid, options) {
            console.log('resourcegrid afterrender fired!');
            this.resourceGrid = grid;
        },
    
    
        onConfigStoreLoad: function(store, records) {
            console.log('Config store loaded with '+records.length+' record(s).');
    
    
            if (records.length && records[0] && records[0].resourcesStore &&
                this.resourceGrid
            ) {
                console.log(
                    'Config store has a resourcesStore with '+
                    records[0].resourcesStore.data.length +
                    ' record(s), reconfiguring resourceGrid!'
                );
                this.resourceGrid.reconfigure(records[0].resourcesStore)
            }
        }
    ...

    Console log

    Code:
    Initialized Configs Controller!
    initComponent GeoPrisma.view.resource.Grid
    resourcegrid afterrender fired!
    Config store loaded with 1 record(s).
    Config store has a resourcesStore with 2 record(s), reconfiguring resourceGrid!

  10. #9
    Sencha User
    Join Date
    Feb 2010
    Posts
    125
    Answers
    7
    Vote Rating
    3
    börn is on a distinguished road

      0  

    Default


    Äh okay .. that should work either...

Turkiyenin en sevilen filmlerinin yer aldigi xnxx internet sitemiz olan ve porn sex tarzi bir site olan mobil porno izle sitemiz gercekten dillere destan bir durumda herkesin sevdigi bir site olarak tarihe gececege benziyor. Sitenin en belirgin ozelliklerinden birisi de Turkiyede gercekten kaliteli ve muntazam, duzenli porno izle siteleri olmamasidir. Bu yuzden iste. Ayrica en net goruntu kalitesine sahip adresinde yayinlanmaktadir. Mesela diğer sitelerimizden bahsedecek olursak, en iyi hd porno video arşivine sahip bir siteyiz. "The Best anal porn videos and slut anus, big asses movies set..." hd porno faketaxi