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.
Related
To do a record update I usually use a CRUD and a store like this:
storeId: 'storeId',
model: 'model',
pageSize: 10,
autoLoad: true,
proxy: {
type: 'ajax',
actionMethods: {
create: 'POST',
read: 'POST',
update: 'POST',
destroy: 'POST'
},
api: {
create: 'php/crud.php?action=create',
read: 'php/crud.php?action=read',
update: 'php/crud.php?action=update',
destroy: 'php/crud.php?action=destroy'
},
reader: {
type: 'json',
rootProperty: 'net',
totalProperty: 'total',
successProperty: 'success'
},
writer: {
type: 'json',
writeAllFields: true,
encode: true,
rootProperty: 'net'
}
}
Logic for the update:
var record = form.getRecord();
record.set(values);
store.sync({
success: function () {
},
failure: function () {
},
callback: function () {
},
});
Problem: just change the value of a database column: YES / NO
Instead of removing a record with 'destroy', I want to just disable it with 'update' a database table column form NO to YES.
In this case I have no form; just a delete button.
I tried without success:
store.proxy.extraParams = {
sub_case: 'change_delete_state',
id_lista: id_lista
},
store.sync({
success: function () {
},
failure: function () {
},
callback: function () {
},
});
And:
Ext.Ajax.request({
url: 'php/crud.php?action=update',
params: {
sub_case: 'change_delete_state',
id_lista: id_lista
},
success: function () {
store.commitChanges();
},
failure: function () {
},
callback: function () {
},
});
I would appreciate suggestions to solve this problem.
EDITED:
Solved like this:
api: {
destroy: 'php/crud.php?action=destroy'
},
cliente-side logic:
// soft delete
store.proxy.extraParams = {
sub_case: 'change_delete_state',
id_lista: id_lista
},
//or
// hard delete
store.proxy.extraParams = {
id_lista: id_lista
},
store.remove(record);
store.sync({...});
server-side (PHP):
case "destroy":{
$record = stripslashes($_POST['net']);
$data = json_decode($record);
$id_lista = $data->{'id_lista'};
if($_REQUEST['sub_case'] == "change_delete_state"){
$sqlQuery = "UPDATE ...";
(...)
}else{
$sqlQuery = "DELETE ...";
(...)
}
}
You are well off if you hide the database logic on the server-side as far as possible.
So, if you only have one way to get rid of a record in the front-end, and the record should be removed from the store, you would just exchange the destroy api of that one "special" store with a special api:
api: {
create: 'php/crud.php?action=create',
read: 'php/crud.php?action=read',
update: 'php/crud.php?action=update',
destroy: 'php/crud.php?action=hide' // hide the record using a SQL update, and remove it from the client-side store; don't remove from server
},
Of course you would have to insert special logic into the crud.php to do the special processing on action=hide.
If you want to have two different ways, one for a "hard delete" and one for a "soft delete", but both should be removed from the store, things become a bit more complicated. You would then need a special boolean "flag" in your record that is processed server-side.
E.g.
fields:[{
name:'hardDelete',
type:'bool',
defaultValue:false
}]
and then you would do sth. along
if(hardDelete) record.set("hardDelete",true);
store.remove(record);
store.sync(
and on the server side you would have to read that flag and act according to its value.
I am facing the same problem as mentioned here: I am trying to connect my ExtJS 4.1 store with REST API, but when I delete the record from the store and consequently invoke HTTP DELETE method, it gets rejected by the server-side because the HTTP request that ExtJS sent contains body. Unfortunately, the accepted answer on the link above is not valid for version 4 of ExtJS and higher.
The best that I achieved so far is to send empty array (literally, [] ) as a body, but of course this is still rejected:
This is my code:
Ext.define('TT.proxy.CustomRestProxy', {
alias: 'proxy.customrestproxy',
extend: 'Ext.data.proxy.Rest',
buildRequest: function(operation) {
var request = this.callParent(arguments);
if(operation.action === 'destroy')
{
delete request.operation.records;
}
return request;
}
});
defineStore = function(storeName, modelName, url) {
var storeProperties = {
extend: 'Ext.data.Store',
requires: modelName,
model: modelName,
id: storeName,
proxy: {
type: 'customrestproxy',
url: url,
batchActions: false,
noCache: false,
headers: { 'Content-Type': 'application/json' },
reader: {
type : 'json',
totalProperty: 'total',
successProperty: 'success',
root: 'data'
},
writer: {
type : 'json'
},
}
};
Ext.define(storeName, storeProperties);
};
I would accept any answer that solves this issue, it does not have to include ExtJS-specific features, i.e. intercepting AJAX request or similar technique is also welcome.
There is a workaround based on AJAX interceptor, inspired by this link. This code solves the problem regardless of the framework used, so it can be also useful for other people who are not necessarily using Ext JS:
(function(XHR) {
"use strict";
var open = XHR.prototype.open;
var send = XHR.prototype.send;
var httpMethod;
XHR.prototype.open = function(method, url, async, user, pass) {
httpMethod = method;
this._url = url;
open.call(this, method, url, async, user, pass);
};
XHR.prototype.send = function(data) {
if(httpMethod === 'DELETE')
{
data = null;
}
send.call(this, data);
}
})(XMLHttpRequest);
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'.
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 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.