i'm trying to save some app settings to the LocalStorage.
I have a model with the LocalStorageProxy, I have a Store with the model and autoload = true.
I sync the store after adding a record.
The corresponding Docs: http://docs-origin.sencha.com/touch/2.4.0/#!/api/Ext.data.proxy.LocalStorage
But after reloading the app in the browser (Chrome) the data are lost. Addidionally to the autoload flag i do a manual store.load() in the launch method of the application.
All is working fine until i reload the app.
Any ideas on that? Thanks!
the model:
Ext.define('LwvMediaReminder.model.Setting', {
extend: 'Ext.data.Model',
requires: [
'Ext.data.Field',
'Ext.data.proxy.LocalStorage'
],
config: {
idProperty: 'settingsId',
fields: [
{
name: 'settingsId',
type: 'int'
},
{
name: 'bPush',
type: 'boolean'
},
{
name: 'bEmail',
type: 'boolean'
},
{
name: 'sEmail',
type: 'string'
},
{
name: 'sToken',
type: 'string'
}
],
proxy: {
type: 'localstorage',
id: 'settings'
}
}
});
the store
Ext.define('LwvMediaReminder.store.SettingsStore', {
extend: 'Ext.data.Store',
alias: 'store.SettingsStore',
requires: [
'LwvMediaReminder.model.Setting'
],
config: {
autoLoad: true,
model: 'LwvMediaReminder.model.Setting',
storeId: 'SettingsStore'
}
});
the method in my SettingsController that should save the settings object, i always use only one record with the id 0:
onSaveSettingsButtonTap: function(button, e, eOpts) { var mainView = this.getMainView(),
store = Ext.getStore('SettingsStore'),
properties = {
settingsId: 0,
bPush: this.getPushCheckbox().isChecked(),
bEmail: this.getEmailCheckbox().isChecked(),
sEmail: this.getEmailField().getValue(),
sToken: this.getTokenField().getValue()
},
record = store.getById(0),
save = true;
// some form validation
if (properties.bEmail) {
if (properties.sEmail === '') {
save = false;
Ext.Msg.alert('Fehler', 'Bitte geben sie auch eine gültige Email-Adresse an.');
}
if (!this.validateEmail(properties.sEmail)) {
save = false;
Ext.Msg.alert('Fehler', 'Die angegebene Email-Adresse ist nicht gültig.');
}
}
// save the record
if (save) {
if (null !== record) {
record.set(properties);
} else {
store.add(properties);
}
store.sync();
mainView.pop();
}
},
I think i have found the solution.
It seems that the LocalstorageProxy has problems with given object ids.
I was setting the Object Id to 0 by default because i wanted only one object at a time with all my settings in one object.
Unfortunatly the local-storage wasn't able to write it to the browser storage.
No I have rewritten the code so that sencha can set the Id by itself. Now it seems to works fine.
And i can access the record by calling the .first() function from the store.
new code snippet:
var store = Ext.getStore('SettingsStore'),
// no preset id anymore
properties = {
bPush: this.getPushCheckbox().isChecked(),
bEmail: this.getEmailCheckbox().isChecked(),
sEmail: this.getEmailField().getValue(),
sToken: this.getTokenField().getValue()
},
// reading the first entry because there is always only one in my app
record = store.first();
I hope that will help somebody in the future.
Related
I used to write this in extjs4:
Ext.define('Superstore', {
extends: 'Ext.data.Store'
config : {
customer : null,
},
applyCustomer : function (value) {
this.customer = value;
},
model : 'Supermodel'
});
I tried the same in extjs6, but with no success:´
Ext.define('Supermodel', {
extend: 'Ext.data.Model',
requires: ['Ext.data.reader.Json', 'Ext.data.proxy.Rest'],
config: {
customer: null
},
fields: [
{name: 'id', type: 'string'},
...
],
proxy: {
type: 'rest',
url: '/customers/{customer}/users',
reader: {
type: 'json'
}
},
applyCustomer: function (value) {
this.customer = value;
this.proxy.url.replace('{customer}', value);
}
});
Did they remove the magic?
Or is there any other, better, way to build my url like in my code?
I've already seen a few solutions, but none of them fitted to my application.
I get the customerId via session which is sent by the backend after login. I would get the store via StoreManager, get the customer record and apply it to the proxy.
Thanks in advance.
If you don't need to manipulate the value use the update function instead:
updateCustomer: function(newValue){
this.proxy.url.replace('{customer}', newValue);
}
(And remove the applyCustomer function)
Ext.define("E.model.P", {
extend: 'Ext.data.Model',
associations: [{
type: 'hasOne',
model: 'E.model.D',
associationKey: 'D',
name:'demo',
getterName: 'getD', // avoid dots in function name
setterName: 'set' // avoid dots in function name
}],
fields: [
{ name: 'id', type: 'int' },
{ name: 'CPR', type: 'string' },
]
});
I have a Store created with the Model P
var store = Ext.create("E.store.MyP");
store.load(function() {
store.each(function(record) {
var info = {
data: Ext.encode(record.getData()),
allData: Ext.encode(record.getData(true)),
personData: Ext.encode(record.getD()) //Here i get the getD is not a function
};
console.log(info);
});
});
The problem I am having is getD is not a function, It will only work if I do not have classes define ex: Ext.define("P").
So how do I access the getD so I can drill further down?
This works http://jsfiddle.net/aqHdC/
Now when I start seperating the classes, It stops working and says can't find function
The associated model (in your example E.model.D) class must be loaded for the getter to be generated.
That means you need to require this class in your base model class definition (or, as you have found out, have all your classes in the same file).
For example:
Ext.define("E.model.P", {
extend: 'Ext.data.Model',
// here's for the class loader!
requires: [
'E.model.D'
],
// rest of your definition
});
I created a model like
Ext.define('MyApp.model.ContainerDetailsModel', {
extend: 'Ext.data.Model',
alias: 'model.ContainerDetailsModel',
config: {
fields: [
{
name: 'id',
allowNull: false,
type: 'string'
},
{
name: 'container_types_id',
type: 'string'
}
]
}
});
and a store like this
Ext.define('MyApp.store.ContainerDetailsStore', {
extend: 'Ext.data.Store',
requires: [
'MyApp.model.ContainerDetailsModel'
],
config: {
model: 'MyApp.model.ContainerDetailsModel',
storeId: 'ContainerDetailsStore',
proxy: {
type: 'ajax',
enablePagingParams: false,
url: 'hereIsServiceUrl',
reader: {
type: 'json'
}
}
}
});
Now somewhere in application I tried to get one record like:
var detailsStore = Ext.getStore("ContainerDetailsStore");
detailsStore.load();
var detailsRecord = detailsStore.last();
But it gaves me undefined. The json returned by service is ok, it use it in different place as source for list. I already tried to change allowNull to true, but there is no null id in source. I tried set types to 'int' with the same result.
So I have tried
console.log(detailsStore);
Result is like this (just important values):
Class {
...
loaded: true,
data: Class {
...
all: Array[1] {
length: 1,
0: Class {
container_types_id: "1",
id: "726",
....
}
...
}
...
},
...
}
In the same place
console.log(detailsStore.data);
returns (as it should):
Class {
...
all: Array[1] {
length: 1,
0: Class {
container_types_id: "1",
id: "726",
....
}
...
}
but (next line)
console.log(detailsStore.data.all);
returns
[]
And it's empty array. When i try any methods from the store it says the store is empty.
I wrote console.log() lines one after another - so for sure it doesn't change between them (I try it also in different order or combinations).
My browser is Google Chrome 23.0.1271.97 m
I use Sencha from https://extjs.cachefly.net/touch/sencha-touch-2.0.1.1/sencha-touch-all-debug.js
How can I take a record from that store?
store.load() Loads data into the Store via the configured proxy. This uses the Proxy to make an asynchronous call to whatever storage backend the Proxy uses, automatically adding the retrieved instances into the Store and calling an optional callback if required. The method, however, returns before the datais fetched. Hence the callback function, to execute logic which manipulates the new data in the store.
Try,
detailsStore.load({
callback: function(records, operation, success) {
var detailsRecord = detailsStore.last();
},
scope: this
});
I'm trying to create simple ExtJs application that manages Users and User's Roles. Set of REST services provide this functionality on back end.
When I assign a new Role to a User, appropriate data store sends POST (create) requests to the service. However when I remove existing Role from a User, it's removed only from store locally without sending DELETE request to the service.
Here is my code:
Model:
Ext.define('UserRole', {
extend: 'Ext.data.Model',
fields: [
{ name: 'Id', mapping: "Id" },
{ name: 'RoleId', mapping: "RoleId" },
{ name: 'UserId', mapping: "UserId" }
]
});
Store With proxy:
Ext.define('UserRoleStore', {
extend: 'Ext.data.Store',
model: 'UserRole',
autoload: false,
proxy: {
type: 'ajax',
reader: {
type: 'json',
root: 'd.results'
},
api: {
read: '/accessmanager.svc/Users(\'{userid}\')/Roles?$format=json',
create: '/accessmanager.svc/UserRoles?$format=json',
update: '/accessmanager.svc/UserRoles?$format=json',
destroy: '/accessmanager.svc/UserRoles?$format=json'
},
updateApiUrlWithUserId: function (userId) {
this.api.read = this.api.read.replace('{userid}', userId);
}
}
});
Method that based on selected checkboxes updates the UserRole store
var chekboxes = Ext.ComponentQuery.query('userdetails #roleslist')[0];
var selectedUserId = this.selectedUserId;
var selectedUserRoleStore = this.selectedUserRoleStore;
Ext.each(chekboxes.items.items, function (cb) {
var exists = false;
Ext.each(selectedUserRoleStore.data.items, function (cs) {
if (cs.data.RoleId === cb.inputValue) {
exists = true;
}
});
if (cb.getValue() && !exists) {
var newRole = Ext.create('UserRole', { RoleId: cb.inputValue, UserId: selectedUserId });
selectedUserRoleStore.add(newRole);
} else if (exists && !cb.getValue()) {
// delete existing role
var record = selectedUserRoleStore.findRecord("RoleId", cb.inputValue);
selectedUserRoleStore.remove(record);
}
});
selectedUserRoleStore.sync();
Presumably your Id field is assigned on the server end when record is created. Correct? First try to specify idProperty: 'Id' in the model. Default value for this is 'id' but I think these are case sensitive.
Using idProperty ExtJs recognizes records as being 'dirty' and required to be updated on the server end.
The issue is your proxy needs to be a specialized REST type:
proxy: {
type: 'rest',
http://docs.sencha.com/ext-js/4-0/#!/api/Ext.data.proxy.Rest
Also, you will probably be able to use the buildURL method to replace your own updateAPI... method.
If got a sencha touch application, with a login form. For returning users, I would like to store the login credentials in the local storage.
User.js
App.models.User = Ext.regModel('User', {
fields: [
{
name: 'username',
type: 'string'
}, {
name: 'password',
type: 'string'
}
],
proxy: {
type: 'localstorage',
id: 'p2s-users'
}
});
Users.js
App.stores.users = new Ext.data.Store({
model: 'User',
autoLoad: true
});
Now I try to sync the form values with local storage, how can I do that, what's the activity flow for reading / getting it?
For reading I would do:
var model = new App.models.User();
users = App.stores.users.load();
if (users.data.length > 0 ) {
model = users.getAt(0);
} else {
App.stores.users.create();
}
form.load(model);
Writing:
form.model.set(form.data);
form.model.save();
App.stores.users.sync();
Somehow it looks too complicate to me (and it doesn't work anyway). How would you solve the problem?
First make sure your saving the models right. For example do this:
var model = new App.models.User();
model.data.username = 'theUser';
model.data.password = 'thePass';
model.save(); //the actual saving. Use chrome developer tools to see the local storage
Then load the model from the localstorage
users = App.stores.users.load();
model = users.getAt(0);
Check if the loaded model is OK and load that to the form with load(model)
The form could be like this:
new Ext.Application({
launch: function() {
new Ext.form.FormPanel({
id:'theForm',
fullscreen: true,
defaults: {
labelAlign: 'top',
labelWidth: 'auto',
},
items: [
{
id : 'userName',
name : 'username',
label: 'Email',
xtype: 'emailfield',
},
{
id : 'userPassword',
name: 'password',
label: 'Password',
xtype: 'passwordfield',
}
]
});
}
});
Then load the record like this Ext.getCmp('theForm').load(users.getAt(0));
To get the model from the form: Ext.getCmp('theForm').getRecord();
From a cursory look, it looks like a possible way to do it.
But, you should create model instances from the model manager, for instance:
Ext.ModelMgr.create({username: 'foo', password: 'bar'}, 'User');