I am on my way to write my first app on sencha touch together with a friend. One of the abilities we want to have in our app is to allow the user to save his personal settings on his device. In order to make it happen we had to teach ourselves how to use local storage proxy.
save my name
To achieve our goal we decided to build the simplest app - get name -> save to file + display on screen + load value on the next app load.
the panels
Form panel - where we get the name and press the button for the update
Display panel - where we display the saved name
The code for the panels:
1: Ext.setup({
2: icon: 'icon.png',
3: glossOnIcon: false,
4: tabletStartupScreen: 'tablet_startup.png',
5: phoneStartupScreen: 'phone_startup.png',
6: onReady: function () {
7:
8: // formpanel for the input
9: var formpanel = new Ext.form.FormPanel({
10: title: 'form',
11: //textfield for the name
12: items: [{
13: xtype: 'textfield',
14: label: 'name',
15: name: 'name'
16: }],
17: //button for the handler (can be replaced by update listener for the text field)
18: dockedItems: [{
19: dock: 'top',
20: items: [{
21: xtype: 'button',
22: text: 'diplay',
23: handler: function () {}
24: }]
25: }]
26:
27: });
28: //panel for display
29: var panel = new PanelExtend({
30: title: 'display2'
31: });
32: //the tab pannel definitions
33: new Ext.TabPanel({
34: fullscreen: true,
35: type: 'dark',
36: sortable: true,
37: items: [formpanel, panel]
38: });
39:
40: }
41:
42: });
43: // create a structure for the pannel so we can use it again if needed
44: var PanelExtend = Ext.extend(Ext.Panel,{
45: title:'empty'
46:
47: });
48:
49: Ext.reg('mypanel',PanelExtend)
In order to update the data in the second page we added a small handler to pannelExtand at the end of the code so the new declaration is:
1: var PanelExtend = Ext.extend(Ext.Panel,{
2: title:'panel',
3: doit: function(name){
4: this.update(name);
5: }
6: });
We also added the handler for the button on the form panel:
1: var formpanel = new Ext.form.FormPanel({
2: title: 'form',
3: items: [{
4: xtype: 'textfield',
5: label: 'name',
6: name: 'name'
7: }],
8: dockedItems: [{
9: dock: 'top',
10: items: [{
11: xtype: 'button',
12: text: 'diplay',
13: handler: function () {
14: //get the value from the field
15: var values = formpanel.getValues();
16:
17: //call the update function
18: panel.doit(values.name);
19: }
20: }]
21: }]
22:
23: });
As you see in the code, in this stage all it does is to activate the handler of the display panel
defining the storage
In order to define the storage to be a local storage proxy we added the following code to the onready function of the Ext.setup:
1: // the sructure for every row in the file
2: var UserSettings = Ext.regModel('UserSettings', {
3: fields: ['id', 'name', 'value']
4: });
5: // the storage
6: var store = new Ext.data.Store({
7: proxy: new Ext.data.LocalStorageProxy({
8:
9: id: 'data',
10: //very important for the row update - basicaly, the row number is taken from the id field in the userSettings structure
11: proxy: {
12: idProperty: 'id'
13: }
14: }),
15: //uses the userSettings structure
16: model: 'UserSettings',
17: autoLoad: true,
18: autoSave: true
19: });
20: //sync with local file
21: store.sync();
22: //what to do when file is read, right now the only thing important to us us the scope
23: store.read({
24: scope: this,
25: callback: function (records) {
26: //code to load the first record
27: }
28: });
Most posts online show how to update a local storage file without taking care of the location of the data in the file. If you build a score record or just want to monitor the user data you do not need to have the idProperty definition but it is important if you want to update a certain row in the file. In our experiment and for the program we develop we wanted to be able to have one line for every variable in the storage, therefore we added the idProperty.
loading the data to the display pannel
Since we already loaded and synced the data we can now use our update function (pannel.doit), we added the following line as the last row of the onrReady function:
1: panel.doit(store.getAt(0).data.value);
The getAt is pointing to the first entry of the file, knowing that it is the only entry. if you build a bigger file, it is advised to build a small function that builds the file structure( fior example: row 0 is name, row 1 is last name, etc…)
saving the data
in the handler of the button, we added the part that saves the data to the file:
1: //read data
2: store.read();
3: //get the first item
4: var item = store.getAt(0);
5: //if not exists, build the first item (this area needs to be replaced with a function that construct a whole settings file
6: if (!item) {
7: //constract item's structure
8: var item = new UserSettings({
9: id: 1, name: 'user name', value: values.name
10: });
11: //add new item to file
12: store.add(item);
13: //sync item
14: store.sync();
15:
16: }
17: //set value in item
18: item.set('value', values.name);
19: //sync items to file
20: store.sync();
Saving the data can be done in two ways – if you want to add a row to a file every time you save all you need to do is to use store.add() and store.sync() but if you do not want to add rows every time you update you need to check if the row exists (add it if not) and then call item.set and store.sync() as it is shown in the code above.
The way we save the data in this example is by assigning a line for every property. this is not a must and for our software needs it will be replaced as a line for every user. All users data can be saved in the same row by changing the structure of the userSettings field. the only thing that I suggest to leave is the id field because it is the connection between the row number and the id of the field.
links
Using data package - from the sencha touch website.
Offline Apps with HTML5: A case study in Solitaire – from the Ed Spencer blog, gave us the basics about storage.
sencha howto – this link was the biggest help to understand the subject of how to load the data, thanks, cipto.