ExtJS: Using remotely loaded singleton values ​​to define a store

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

I have an application that uses parse.com to store data, I want each user to have a different parse.com account, so their datasets do not overlap at all. So I created singleton (Settings), which stores the user appId and apiKey, which are downloaded from the general parse.com account, which is managed by me, and contains each user email address, appId and apiKey, so when they enter the application, it gets user appId and apiKey.

The thing is, I need to use these settings, appId and apiKey, in the definitions of my stores, since I need to send them to the headers. I did some testing trying to set my singleton globals when the application starts, but during the store definition both of these β€œglobals” are equal to zero, because the application is not running yet.

Here are some of my code, so I can make myself a little clearer, since I know that this is not 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": " useremail@gmail.com "}' //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(); } } ); } }); 

Score

 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 }); 

How does this happen?

By the way, if someone can think of their own name for this topic, feel free to change it or suggest it.

+7
javascript singleton extjs store
source share
3 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": " useremail@gmail.com "}' //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(); } } ); } }); 
+1
source share

I would suggest using routes to accomplish this since you are using ExtJs 6. This is completely out of the box, but I think that would be ideal for your situation. Thus, you can just make sure that when you call the route and download part of your application, you can always perform some checks. This can be very useful for checking user credentials, for example. More information on routes can be found here. And this is a great post when you want to process user sessions through routes.

Singleton:

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

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' } } } }); 

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": " useremail@gmail.com "}' //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": " useremail@gmail.com "}' //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(); } }); 
+1
source share

I think that the problem can be solved by moving the proxy server definition to the "Things" storage constructor, as described below.

 Ext.define('MyApp.store.Things', { extend: 'Ext.data.Store', model: 'MyApp.model.Thing', autoLoad: true, autoSync: true, constructor: function(config) { config = Ext.apply({ 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, 'X-Parse-REST-API-Key': Settings.appId, 'Content-Type': 'application/json' } } }, config); this.callParent([config]); } }); 

When the proxy definition is inside the constructor, Settings.appId and Settings.apiKey are only allowed when creating an instance of "MyApp.store.Things".

+1
source share

All Articles