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": "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();
}
}
);
}
});
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.
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();
}
}
);
}
});
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": "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();
}
});
I think the issue can be solved by moving proxy definition to constructor of 'Things' store as given 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 proxy definition is inside the constructor, Settings.appId and Settings.apiKey are resolved only at the time of instance creation of 'MyApp.store.Things'.
Related
I have a grid store where I am using Ext.data.Store and loading the value. below is the method where I am giving a post requesting, getting the data and loading by using store.on(load).
myGridStore: function(myXml) {
var me = this,store;
me.setLoading(true);
store = new Ext.data.Store({
proxy: new Ext.data.proxy.Ajax({
actionMethods: {
read: 'POST'
},
url: 'someUrl',
headers: {
'Accept': 'text/xml; charset=utf-8'
},
reader: {
type: 'xml',
record: 'I',
rootProperty: 'R'
},
extraParams: {
strIPXML: myXml
}
}),
sortOnLoad : true,
autoLoad: true,
remoteFilter: false,
multiSelect: true,
fields: me.fields,
});
store.on('load', function(thistore, records , successful , operation , eOpts){
me.store.loadData(thistore.data.items);
});
return store;
},
now I want my store to bufferedStore so for that I changed Ext.data.Store to Ext.data.BufferedStore But in bufferedStore I can not use store.on(load) Like I commented the code, below is the code and then grid is loading. But when second time I am applying the myXml I am not able to set the data because store.on(load) is not working.
myGridStore: function(myXml) {
var me = this,store;
me.setLoading(true);
store = new Ext.data.Store({
pageSize: 100,
leadingBufferZone: 100,
proxy: new Ext.data.proxy.Ajax({
actionMethods: {
read: 'POST'
},
url: 'someUrl',
headers: {
'Accept': 'text/xml; charset=utf-8'
},
reader: {
type: 'xml',
record: 'I',
rootProperty: 'R'
},
extraParams: {
strIPXML: myXml
}
}),
sortOnLoad : true,
autoLoad: true,
remoteFilter: true,
fields: me.fields,
});
/*store.on('load', function(thistore, records , successful , operation , eOpts){
me.store.loadData(thistore.data.items);
});*/
return store;
},
Can anyone help me how to make it work. How to set the data in bufferedStore which i can easily able to set in Ext.data.store
Error : LoadData may not be used on a buffered store - the store is a map of remote data
The ExtJS documentation for the store.load event says:
Note: If you are using a buffered store, you should use prefetch.
Have you tried moving your function to the prefetch event to see if that works for you?
...
store.on('prefetch', function(...
I created a store, where I'm loading nested data from .json file:
var userStore = Ext.create('Ext.data.Store', {
model: 'User',
storeId:'2013',
autoLoad: true,
pageSize: 4,
proxy: {
type: 'ajax',
url: 'data/users.json',
reader: {
type: 'json',
root: 'users',
totalProperty: 'total'
},
writer: {
type: 'json'
}
}
});
To add any new data to grid I use:
var asdfg = Ext.getStore(myNewGrid);
asdfg.add({lastname: nowa, firstname: nowa2);
Everything works fine until I refreshed the page. After it I lose all changes.
My model 'User' file:
Ext.define('MyApp.controller.Users', {
extend: 'Ext.app.Controller',
border: false,
views: [
'user.List'
],
init: function() {
this.control({
'viewport > panel': {
render: this.onPanelRendered
}
});
},
onPanelRendered: function() {
console.log('The panel was rendered');
}});
Is it any simple way to save and commit my new changes similar to loading? To start my web use Sencha Cmd v.4.0.4
just use autoSync:true in your store.
in that case adding type:rest to your proxy will make it easier.
look at this example: http://dev.sencha.com/deploy/ext-4.0.1/examples/restful/restful.html
I am trying to have it so that once a user is logged in and they click refresh they will stay on the same page. However right now, when a user is logged in and clicks refresh they are sent back to the login screen. I know session storage is used for while the browser isn't closed, which is what I need. I can't seem to get it to work properly though.
model
Ext.define('MeterReadingsApp.model.Login', {
extend: 'Ext.data.Model',
config: {
fields: [{name: "username", type:'string'}, {name: "password",
type:'string'}],
identifier: 'uuid'
}
});
store
Ext.define('MeterReadingsApp.store.Login', {
extend: 'Ext.data.Store',
//requires: ['Ext.data.proxy.SessionStorag'],
config: {
model: 'MeterReadingsApp.model.Login',
//sessionStorage.type:
proxy: {
//use sessionstorage if need to save data for that
//specific session only
type: 'sessionstorage',
id : 'Login'
},
autoLoad: false
}
});
//var Login = Ext.create('MeterReadingsApp.store.Login');
//Login.load();
app.js
launch: function() {
// Destroy the #appLoadingIndicator element
Ext.fly('appLoadingIndicator').destroy();
var session=Ext.getStore('Login');
session.load();
var record = session.getAt('userName');
alert(record);
if(record != undefined){
//exits to main menus not login
}
else
Ext.Viewport.add(Ext.create('MeterReadingsApp.view.Login'));
},
controller
loginButton: function(){
// var me = this;
Ext.Ajax.request({
useDefaultXhrHeader:false,
url: getLogonUrl(),
method: 'POST',
headers: { 'Content-Type' : 'application/x-www-form-urlencoded' },
params : {
"userName": Ext.getCmp('username').getValue(),
"password": Ext.getCmp('password').getValue()
},
success: function (response) {
Ext.getCmp('failLogin').hide(),
Ext.getStore('Login').sync();
Ext.Viewport.setActiveItem({xtype: 'Main'});
Ext.getStore('Campuses').load();
},
failure: function(response) {
Ext.getCmp('loginform').doSetHeight(250),
Ext.getCmp('failLogin').show();
}
});
},
thanks for the help!
You need to set the storeId property on the store. You are trying to use the proxy's id to get the store.
I'm trying to integrate kendoGrid on a Backbone View, this is my view code:
App.Views.UsersManager = Backbone.View.extend({
tagName: 'section',
id: 'users-manager',
className: 'tile',
template: Handlebars.compile($('#profile-usersManager-template').html()),
render: function () {
console.log('usersManager.render -> collection', this.collection);
var self = this;
this.$el.html(this.template());
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: '/users',
type: 'GET',
dataType: 'json'
},
update: {
url: '/users',
type: 'PUT',
dataType: 'json'
}
},
schema: {
data: 'data'
},
batch: true
});
this.$('table.users-manager').kendoGrid({
scrollable: false,
sortable: true,
dataSource: dataSource,
toolbar: ["save"],
editable: true,
navigatable: true,
// filterable: true,
});
return this;
}
});
The view render correctly, and the kendoGrid correctly GET my users data from my SlimPHP framework, but when i try to modify an element of the grid and hit the "Save Changes" button provided by "toolbar: ["save"]", nothing happens, even on my firebug console... there's no server communication at all.
I'm new on kendo (and Backbone also) development, maybe i'm failing something on the syntax? :stuck:
Update after Atanas Korchev answer
this is my DataSource updated:
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: '/users',
type: 'GET',
dataType: 'json'
},
update: {
url: '/users',
type: 'PUT',
dataType: 'json'
}
},
schema: {
data: 'data',
model: {
id: 'id',
fields: {
email: {},
name: {},
surname: {},
rank: {},
type: {}
}
}
},
batch: true
});
That not solve my issue, i wanna notice that my php code look like that actually:
$app->put('/users', function () use ($app, $db) {
exit('put ok');
});
Just to see if the client/server communication works... I know it will be an error, but I can't see any firebug error too, like the "Save Changes" button has no event... (I will try the Dennis Rongo suggestion.. but I dont think is the solution...)
Sorry for my bad english
Try describing your model in the DataSource settings:
schema: {
data: 'data',
model: {
id: "MyId"
}
}
You need to at least specify the id.
Solved by removing the data: 'data' from the schema object, there's the link kendoGrid batch editing!
I am working on a Sencha Touch application and I am learning it great because I love JavaScript.
This is my app.js
var App = new Ext.Application({
name: 'My First App',
//BaseURL: 'http://mydomain.com/testing/first/services/',
launch: function() {
this.views.viewport = new this.views.Viewport();
// this.BaseURL = "http://mydomain.com/testing/first/services/";
}
});
This is one of my Store.
var newsStore = new Ext.data.Store({
model: 'News',
sorters: [{
property: 'PostedOn',
direction: 'DESC'
}],
proxy: {
type: 'ajax',
url: 'http://mydomain.com/testing/first/services/News.php',
reader: {
type: 'xml',
root: 'News',
record: 'New'
}
},
getGroupString: function(record) {
if (record && record.data.PostedOn) {
return record.get('PostedOn').toDateString();
}
else {
return '';
}
},
autoLoad: true
});
Now the question is, if I can create a global variable across whole application? It's named BaseURL and I can use it among all Data Stores and when need to change it, I just change this to reflect across whole application.
I need to know two things.
How to declare a global application level variable.
How to access that variable in views and stores.
I would recommend adding your custom global variables to the application namespace, like this:
Ext.application({
name: 'MyApp',
launch: function() { },
apiToken: 'foo'
});
This way you will be able to access these custom variables after your application has launched:
MyApp.app.apiToken
It works with functions, too:
Ext.application({
name: 'MyApp',
launch: function() { },
apiToken: 'foo',
getApiToken: function() { return this.apiToken; }
});
You can declare a global variable normally as you would do without Sencha:
var BaseURL = "http://mydomain.com/testing/first/services/";
And then to use it:
proxy: {
type: 'ajax',
url: BaseUrl + 'News.php',
reader: {
type: 'xml',
root: 'News',
record: 'New'
}
}
EDIT :
If you want to declare it as a member of your App instance do:
var App = new Ext.Application({
name: 'My First App',
launch: function() {
this.views.viewport = new this.views.Viewport();
this.BaseURL = "http://mydomain.com/testing/first/services/";
}
});
and then:
proxy: {
type: 'ajax',
url: App.BaseUrl + 'News.php',
reader: {
type: 'xml',
root: 'News',
record: 'New'
}
}
After some sencha updates we can do it:
var App = Ext.application({
name: 'Myapp',
serviceUrl: 'https://example',
launch: function() {
}
});
Ext.Ajax.request({
url: Myapp.app.servideUrl,
withCredentials: true,
useDefaultXhrHeader: true,
method: 'post',
scope: this,
params: {
cmd: 'connect',
id: login,
password: pass,
version: 1
},
success: function (response) {
var result = Ext.JSON.decode(response.responseText);
if (result.result.status === 'connected'){
this.loginSucess(result);
}else{
this.loginFail(result);
}
},
failure: function (response) {
this.loginFail();
}
});
This answer, may help You.
Specially if, You want to pass params to store.