Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ExtJS: Using remotely loaded singleton values for store definition

I'm having some trouble trying to figure out how to do this (if it's even possible).

I have an app which uses parse.com to store it's data, the thing is I want each user to have a different parse.com account so their data sets don't intersect whatsoever. So I created a singleton (Settings) which stores the user's appId and apiKey, which are loaded from a general parse.com account which is managed by me and contains each user's email, appId and apiKey, so when they log into the app it gets the user's appId and apiKey.

The thing is I need to use those settings, appId and apiKey, in the definitions of my stores, as I need to send them in the headers. I've done some testing trying to set my singleton's globals when the app launchs, but at the time of the stores definition both of those "globals" are null, as the app hasn't launched yet.

Here's some of my code so I can make myself a little clearer as I know this isn't the easiest thing to understand.

Application.js

Ext.define('Settings', {
    singleton: true,        
    appId: null,
    apiKey: null
});


Ext.define('MyApp.Application', {
    extend: 'Ext.app.Application',        
    name: 'MyApp',        
    stores: [],
    launch: function () {
        Ext.create('MyApp.store.Settings').load({
            params: {
                'where': '{"email": "[email protected]"}' //email is supposed to be a user input but for the sakes of testing I just made it static
            },
            callback: function(records){
                var s = records[0];
                Settings.appId = s.get('appId');
                Settings.apiKey = s.get('apiKey');
                Parse.initialize(Settings.appId, Settings.apiKey);
            }
        });
    },


    onAppUpdate: function () {
        Ext.Msg.confirm('Application Update', 'This application has an update, reload?',
            function (choice) {
                if (choice === 'yes') {
                    window.location.reload();
                }
            }
        );
    }
});

Store

Ext.define('MyApp.store.Things', {
    extend: 'Ext.data.Store',        
    model: 'MyApp.model.Thing',        
    proxy: {
        type: 'rest',
        api: {
            read: 'https://api.parse.com/1/classes/Thing',
            create: 'https://api.parse.com/1/classes/Thing'
        },
        reader: {
            type: 'json',
            rootProperty: 'results'
        },
        useDefaultXhrHeader: false,
        withCredentials: false,
        headers: {
            'X-Parse-Application-Id': Settings.appId, //this is null at the time of definition, but I want it to be the newly fetched value at the time of app launch
            'X-Parse-REST-API-Key': Settings.apiKey, //this is obviously null as well
            'Content-Type': 'application/json'
        }
    },
    autoLoad: true,
    autoSync: true
});

What's the way around this?

By the way.. if someone can think of a proper name for this thread please feel free to change it or suggest.

like image 648
martskins Avatar asked Aug 26 '15 14:08

martskins


2 Answers

Try something like:

Ext.define('Settings', {
    singleton: true,
    appId: null,
    apiKey: null
});

Ext.define('MyApp.store.Things', {
    extend: 'Ext.data.Store',

    model: 'MyApp.model.Thing',

    proxy: {
        type: 'rest',
        api: {
            read: 'https://api.parse.com/1/classes/Thing',
            create: 'https://api.parse.com/1/classes/Thing'
        },
        reader: {
            type: 'json',
            rootProperty: 'results'
        },
        useDefaultXhrHeader: false,
        withCredentials: false,
    },
    //autoLoad: true,
    autoSync: true
});

Ext.define('MyApp.Application', {
    extend: 'Ext.app.Application',

    name: 'MyApp',


    stores: ['Things'],
    launch: function() {
        var settings = Ext.create('MyApp.store.Settings');
        settings.on('load', function() {
            var things = Ext.getStore('Things');
            things.getProxy().setHeaders({
                'X-Parse-Application-Id': Settings.appId, 
                'X-Parse-REST-API-Key': Settings.apiKey, 
                'Content-Type': 'application/json'
            });
            things.load();
        });

        settings.load({
            params: {
                'where': '{"email": "[email protected]"}' //email is supposed to be a user input but for the sakes of testing I just made it static
            },
            callback: function(records) {
                var s = records[0];
                Settings.appId = s.get('appId');
                Settings.apiKey = s.get('apiKey');
                Parse.initialize(Settings.appId, Settings.apiKey);
            }
        });
    },


    onAppUpdate: function() {
        Ext.Msg.confirm('Application Update', 'This application has an update, reload?',
            function(choice) {
                if (choice === 'yes') {
                    window.location.reload();
                }
            }
        );
    }
});
like image 192
Guilherme Lopes Avatar answered Sep 18 '22 04:09

Guilherme Lopes


I would suggest using routes to accomplish this, since you are using ExtJs 6. It is completely out of the box, but I thing it would be ideal for your situation. In this way you can simply be sure that when a route is called and a part of your application is loaded, you always can do some checks. This can be very useful for checking user credentials for example. More information about routes can be found here. And this is a great post when you want to handling user sessions through routes.

The singleton:

Ext.define('Settings', {
    singleton: true,        
    appId: null,
    apiKey: null
});

The Base store:

Ext.define('Base', {
    extend: 'Ext.data.Store',
    alias: 'store.base',
    storeId: 'base',

    autoLoad: false,

    proxy: {
        type: 'rest',
        useDefaultXhrHeader: false,
        withCredentials: false
    },

    listeners: {
        beforeload: function(store, operation, eOpts) {
            store.getProxy().headers = {
                'X-Parse-Application-Id': Settings.appId,
                'X-Parse-REST-API-Key': Settings.apiKey,
                'Content-Type': 'application/json'
            }
        }
    }
});

The Things store:

Ext.define('MyApp.store.Things', {
    extend: 'MyApp.store.Base',        
    alias: 'store.things',
    model: 'MyApp.model.Thing',        

    storeId: 'things',

    requires: [
        'Settings'
    ],

    proxy: {
        api: {
            read: 'https://api.parse.com/1/classes/Thing',
            create: 'https://api.parse.com/1/classes/Thing'
        },
        reader: {
            type: 'json',
            rootProperty: 'results'
        }
    },
    autoLoad: false, // --> set to false
    autoSync: true
});

Your MainController:

Ext.define('MyApp.view.main.MainController', {
    extend : 'Ext.app.ViewController',

    requires: [
        'Settings'
    ],

    stores: [
        'Things'
    ],

    routes : {
        'user/:id' : {
            before  : 'onBeforeUser',
            action  : 'onUser'
        }
    },

    onBeforeUser : function(id, action) {
        Ext.create('MyApp.store.Settings').load({
            params: {
                'where': '{"email": "[email protected]"}' //email is supposed to be a user input but for the sakes of testing I just made it static
            },
            callback: function(records){
                var s = records[0];
                Settings.appId = s.get('appId');
                Settings.apiKey = s.get('apiKey');
                Parse.initialize(Settings.appId, Settings.apiKey);
                action.resume();
            }
        });

        // or even better

        Ext.Ajax.request({
            url: 'url/to/the/api',
            params: {
                'where': '{"email": "[email protected]"}' //email is supposed to be a user input but for the sakes of testing I just made it static
            },
            success: function(response, opts) {
                var obj = Ext.decode(response.responseText);

                Settings.appId = obj.appId;
                Settings.apiKey = obj.apiKey;
                Parse.initialize(Settings.appId, Settings.apiKey);
                action.resume();
            },
            failure: function(response, opts) {
                action.stop(true);
            }
        });
    },

    onUser : function(id) {
        Ext.getStore('things').load();
    }
});
like image 35
Tarabass Avatar answered Sep 22 '22 04:09

Tarabass