Ext.data.LocalStorage not working on Offline Mode - extjs

Im now studying Sencha Touch 2 and doing some Research on Ext.data.LocalStorage that can be use in Offline Mode.
I tried to follow this turorial
Sencha Touch 2 Local Storage
and just updated the code from Github - RobK/SenchaTouch2-LocalStorageExample or riyaadmiller/LocalStorage and modified Store url using my own WCF Rest
but i cant get LocalStorage working on offline mode.I have no issue on running the app Online. I also tried to debug it on Chrome developer tool but LocalStorage always get 0 data. I used Chrome/Safari Browser and also build the apps as Android using Phonegap build and still not working.
Did I miss something?
Does anyone can provide the details to deal with this Issue.
Below is my code:
Store:
Ext.define('Local.store.News', {
extend:'Ext.data.Store',
config:{
model: 'Local.model.Online',
proxy:
{
type: 'ajax',
extraParams: { //set your parameters here
LookupType: "Phone",
LookupName: ""
},
url: 'MY WCF REST URL',
headers: {
'Content-Type': 'application/json; charset=utf-8'
},
reader:
{
type: 'json'
, totalProperty: "total"
},
writer: { //Use to pass your parameters to WCF
encodeRequest: true,
type: 'json'
}
},
autoLoad: true
}
});
Offline Model:
Ext.define('Local.model.Offline', {
extend: 'Ext.data.Model',
config: {
idProperty: "ID", //erm, primary key
fields: [
{ name: "ID", type: "integer" }, //need an id field else model.phantom won't work correctly
{ name: "LookupName", type: "string" },
{ name: "LookupDescription", type: "string" }
],
identifier:'uuid', // IMPORTANT, needed to avoid console warnings!
proxy: {
type: 'localstorage',
id : 'news'
}
}
});
Online Model:
Ext.define('Local.model.Online', {
extend: 'Ext.data.Model',
config: {
idProperty: "ID", //erm, primary key
fields: [
{ name: "ID", type: "integer" }, //need an id field else model.phantom won't work correctly
{ name: "Name", type: "string" },
{ name: "Description", type: "string" }
]
}
});
Controller:
Ext.define('Local.controller.Core', {
extend : 'Ext.app.Controller',
config : {
refs : {
newsList : '#newsList'
}
},
/**
* Sencha Touch always calls this function as part of the bootstrap process
*/
init : function () {
var onlineStore = Ext.getStore('News'),
localStore = Ext.create('Ext.data.Store', { storeid: "LocalNews",
model: "Local.model.Offline"
}),
me = this;
localStore.load();
/*
* When app is online, store all the records to HTML5 local storage.
* This will be used as a fallback if app is offline more
*/
onlineStore.on('refresh', function (store, records) {
// Get rid of old records, so store can be repopulated with latest details
localStore.getProxy().clear();
store.each(function(record) {
var rec = {
name : record.data.name + ' (from localStorage)' // in a real app you would not update a real field like this!
};
localStore.add(rec);
localStore.sync();
});
});
/*
* If app is offline a Proxy exception will be thrown. If that happens then use
* the fallback / local stoage store instead
*/
onlineStore.getProxy().on('exception', function () {
me.getNewsList().setStore(localStore); //rebind the view to the local store
localStore.load(); // This causes the "loading" mask to disappear
Ext.Msg.alert('Notice', 'You are in offline mode', Ext.emptyFn); //alert the user that they are in offline mode
});
}
});
View:
Ext.define('Local.view.Main', {
extend : 'Ext.List',
config : {
id : 'newsList',
store : 'News',
disableSelection : false,
itemTpl : Ext.create('Ext.XTemplate',
'{Name}-{Description}'
),
items : {
docked : 'top',
xtype : 'titlebar',
title : 'Local Storage List'
}
}
});
Thanks and Regards

1) First of all when you creating record and adding into store, the record fields should match the model fields of that store.
Here you creating record with field name, but Local.model.Offline didn't name field
var rec = {
name : record.data.name + ' (from localStorage)'
};
This is what you need to do within refresh
localStore.getProxy().clear();
// Also remove all existing records from store before adding
localStore.removeAll();
store.each(function(record) {
console.log(record);
var rec = {
ID : record.data.ID,
LookupName : record.data.Name + ' (from localStorage)',
LookupDescription : record.data.Description
};
localStore.add(rec);
});
// Don't sync every time you add record, sync when you finished adding records
localStore.sync();
2) If specify idProperty in model which is using localStorage, then record will not be added into localStorage.
Model
Ext.define('Local.model.Offline', {
extend: 'Ext.data.Model',
config: {
// idProperty removed
fields: [
{ name: "ID", type: "integer" }, //need an id field else model.phantom won't work correctly
{ name: "LookupName", type: "string" },
{ name: "LookupDescription", type: "string" }
],
identifier:'uuid', // IMPORTANT, needed to avoid console warnings!
proxy: {
type: 'localstorage',
id : 'news'
}
}
});

Related

ExtJS store filter is being sent not in full

I've a store syncronized with remote db model. I need to apply remote filtering. Problem is that if i set a filter in config options the filter is being sent (on load or on sync) but not fully.
Store:
var RegularItemsStore=Ext.create("appMain.Store.UniversalStore",{
model: 'OrderModel',
modelName:'Order2',
autoSync: true,
filters: [{ "property" : "storeId", "value": 0 , "type": "numeric", "operator": "="},
});
in Http ajax request this filter is passed with ONLY "property" : "storeId", "value": 0, the "type": "numeric", "operator": "=" are missed; in web-dev tools:
Query String Parameters
r:backend/index
Table:Order2
log:0
...
filter:[{"property":"storeId","value":0}]
while if i set filter on the proxy pertaining to store, the filter is passed to server unchanged (in right way):
Proxy config:
this.proxy =
{
url: "index.php?r=backend/index&Table=" + this.modelName + this.params,
reader: {
root: "result.data",
totalProperty: "result.count",
type: "json",
metaProperty: 'myMetaData', // config for metaData:
},
actionMethods: {
read: 'GET', update: 'POST'
},
...
};
and filter applying:
Ext.each(ItemStoreArray, function(store){
var filter = [ { property: 'contractorId', value: ContractorSelectedId , operator: '=', type: 'numeric' }, { property: 'userId', value: UserId , operator: '=', type: 'numeric' }];
store.getProxy().setExtraParam('filter' , Ext.JSON.encode(filter) );
store.load(); //console.dir(store);
});
How to resolve it? Should i set a permanent filter on proxy in the store init, how?
Update
As followed Alexander's recommendation i've overriden the proxy's config parameter that solved the issue:
encodeFilters: function(filters) {
var min = [],
length = filters.length,
i = 0;
for (; i < length; i++) {
min[i] = {
property: filters[i].property,
value : filters[i].value,
operator : filters[i].operator, // added
type : filters[i].type, // added
};
}
return this.applyEncoding(min);
},
You can override encodeFilters: function(filters) in the proxy you use.
For the default implementation have a look at src/data/proxy/Server.js.

Creating a model for two jsonarray

demoAlerts({
itemstatus: [
{
item: "1",
name: "apple",
type: "fruit"
},
{
item: "2",
name: "pine",
type: "fruit"
}
],
deliverystatus: [
{
name: "james",
status: "yes"
},
{
name: "thomas",
status: "no"
},
]
});
I have two array (itemstatus and deliverystatus), I need to create the model for this store. what I tried is
ParentModel:
Ext.define('test.model.ParentModel', {
extend: 'Ext.data.Model',
requires:['test.model.ItemModel','test.model.DeliveryModel'],
autoLoad: true,
config : {
fields : [ 'itemstatus', {
name : 'demostatuslist',
model : 'demoAlerts.model.ItemModel',
mapping : 'itemstatus'
},
'portalstatus', {
name : 'deliverystatus',
model : 'test.model.DeliveryModel',
mapping : ' deliverystatus'
}]
}
});
ItemModel
Ext.define('demoAlerts.model.ItemModel', {
extend: 'Ext.data.Model',
config: {
fields: [
{ name: 'item', type: 'string' },
{ name: 'name', type: 'string' },
{ name: 'type', type: 'string' }
]
}
});
DeliveryModel
Ext.define('demoAlerts.model.DeliveryModel', {
extend: 'Ext.data.Model',
config: {
fields: [
{ name: 'name', type: 'string' },
{ name: 'status', type: 'string' },
]
}
});
Whether i properly configured the model. I am receiving the store as empty
Use Associations :) http://docs.sencha.com/touch/2.3.1/#!/api/Ext.data.association.Association
In this case I would have a Model with 2 hasMany associations like this:
Ext.define('demoAlerts.model.ContainerModel', {
extend : 'Ext.data.Model',
requires : [
'demoAlerts.model.DeliveryModel',
'demoAlerts.model.ItemModel'
],
config : {
associations: [
{
type : 'hasMany',
model : 'demoAlerts.model.DeliveryModel',
associationKey : 'deliveryStatus',
name : 'deliveryStatus',
autoLoad : true // this is very important
},
{
type : 'hasMany',
model : 'demoAlerts.model.ItemModel',
associationKey : 'itemStatus',
name : 'itemStatus',
autoLoad : true // this is very important
}
]
}
});
Then use a store SomeStore binded to ContainerModel.
IMPORTANT Each record in SomeStore will have deliveryStatusStore and itemStatusStore AUTOGENERATED.
Read about associations.
Neither http://docs.sencha.com/touch/2.3.1/#!/api/Ext.data.Field
nor http://docs.sencha.com/extjs/5.0/apidocs/#!/api/Ext.data.field.Field
knows a valid config option "model" for a field.
As far as I know, there is no such thing as a "Parent Model" available in ExtJS or Sencha Touch.
As far as I know, there is no possibility to have two stores in one.
You can load two (or more) stores using only one call to the server like in my following example:
firststore.on('load',function() {
secondstore.loadRawData(firststore.getProxy().getReader().rawData);
});
firststore.load()
Where you would give firststore the server url and the root of the data that goes into the first store, and secondstore will have the root of the data that goes into the second store.
Please be aware that the second store won't be filled if zero records go into the first store, and choose your stores appropriately.
If any of your stores can be the only empty store, perhaps you will have to get the rawdata via Ext.data.Request and load it into all stores afterwards.

The URL of an ajax proxy - Ext JS

I have a couple of questions about the url field of an ajax proxy, and Ext.Ajax.request
I'm getting a JSON response from an Ext.Ajax.request, and sending that data to a store. (I'm also trying to use the pagingToolbar, which is highly uncooperative at the moment)
Anyhow, the paging only seems to slightly work when I use an ajax proxy, however I'm not sure what to put in as the URL. Currently it's url: ''
var store = Ext.create('Ext.data.Store', {
storeId : 'resultsetstore',
autoLoad : false,
pageSize : itemsPerPage,
fields: [
{name : 'id', type : 'auto'},
{name : 'name', type : 'auto'},
{name : 'description', type : 'auto'}
],
proxy: {
type : 'ajax',
url : '???',
reader: {
type : 'json',
root : 'elements'
}
}
});
It seems the url reads data from a .json file in a specific directory (i.e. url: 'myData/data.json'), but there isn't any file like that to read from, as my response is coming back as a JSON Object.
And here is my request/response, which I parse and send to my store:
var request = Ext.Ajax.request({
url : 'MCApp', //here I specify the Servlet to be read from
jsonData : searchquery, //A JSON Object
params:{
start:0,
limit: itemsPerPage
},
success : function(response) {
mainresponse = response.responseText;
//etc.
}
Is having a separate request redundant?
Could I accomplish this within my store alone (passing my searchquery as a parameter to the server and all that jazz)?
I apologize for this jumbled question in advance!
Cheers
You can use a memory proxy and set the store data with the data property, but I don't recommend that.
If I where you I would forget the ajax request and start take advantage of the store's proxy.
Here's an example
var store = Ext.create('Ext.data.Store', {
storeId: 'resultsetstore',
autoLoad: false,
pageSize: 20,
fields: ['id','name','description'],
proxy: {
type: 'ajax',
url: 'urlToTheServlet', //here I specify the Servlet to be read from
extraParams: {
searchquery: 'Test'
}, //A String Object
reader: {
type: 'json',
root: 'elements'
}
}
});
store.load();
note that the start, limit are dealt with in the background. You don't have to set them manually. You can set a pageSize but it has it's own default, so it's not required.
This is what your data is expected to look like:
{
"elements": [
{
"id": 1,
"name": "John",
"description": "Project Manager"
},
{
"id": 2,
"name": "Marie",
"description": "Developer"
},
{
"id": 3,
"name": "Tom",
"description": "Technical Lead"
}
]
}
UPDATE: Passing an object as payload to the proxy
I had the same issue and I couldn't find an out of the box solution so I wrote my own proxy to resolve this.
Ext.define('BCS.data.proxy.AjaxWithPayload', {
extend: 'Ext.data.proxy.Ajax' ,
alias: 'proxy.ajaxwithpayload',
actionMethods: {
create: "POST",
destroy: "POST",
read: "POST",
update: "POST"
},
buildRequest: function(operation) {
var me = this,
request = me.callParent([operation]);
request.jsonData = me.jsonData;
return request;
}
});
Now you can do this:
var store = Ext.create('Ext.data.Store', {
storeId: 'resultsetstore',
autoLoad: false,
pageSize: 20,
fields: ['id','name','description'],
proxy: {
type: 'ajaxwithpayload',
url: 'urlToTheServlet', //here I specify the Servlet to be read from
jsonData : YOUR_OBJECT
reader: {
type: 'json',
root: 'elements'
}
}
});
I prefer to keep each method in a separated endpoint:
proxy: {
type: 'ajax',
reader: {
type: 'json'
},
api: {
read: 'getCenarioTreeNode', // To request a node children (expand a node)
create: 'createCenarioTreeNode', // When you insert a node
update: 'updateCenarioTreeNode', // When you change a node attribute
destroy: 'destroyCenarioTreeNode' // When you delete a node
},
writer: {
type:'json',
encode:true,
rootProperty:'data'
}
},

How to create Grid in sencha touch 2.3.0 populate data from a REST webservice

I need to display report in Grid / Table in Sencha Touch 2.3.0. Is there any build in function to do so.
The store needs to populate data from a REST webservice call.
For loading data you can use Ext.data.Store configured with REST proxy Ext.data.proxy.Rest
For displaying data from store you can use Ext.grid.Grid of Ext.dataview.DataView
I do this all the time with something like this:
(Though I haven't worked with the Grid, I'm quite sure the same principles apply...)
Ext.define('App.controller.GridController', {
extend : 'Ext.app.Controller',
config: {
refs: {
getApiButton: 'button[action=getApiData]'
},
control: {
'getApiButton' : {
tap : 'onButtonTap'
}
}
},
onButtonTap : function(field, value) {
var that = this;
Ext.Ajax.request({
url : someWebServiceUrl,
method: 'GET',
success: function (result, request) {
var res = Ext.decode(result.responseText);
if (res.success === true && res.data != false) {
var recipient = {
name: res.data[0].displayname,
picId: res.data[0].pictureid,
gender: res.data[0].gender
};
var mod = Ext.define('App.model.GradingPopModel', {
extend: 'Ext.data.Model',
config: {
fields: [
'name',
'picId',
'gender'
]
}
});
/* == this is probably where you want to make your changes to apply the model to the grid template
the sencha website has this:
data: {'items': [
{ 'name': 'Lisa', "email":"lisa#simpsons.com", "phone":"555-111-1224" },
{ 'name': 'Bart', "email":"bart#simpsons.com", "phone":"555-222-1234" },
{ 'name': 'Homer', "email":"home#simpsons.com", "phone":"555-222-1244" },
{ 'name': 'Marge', "email":"marge#simpsons.com", "phone":"555-222-1254" }
]}
*/
var store = Ext.create('Ext.data.Store', {
model: mod,
storeId:'recipStore'
});
store.add(recipient);
store.setData(recipient);
store.load();
var gridView = Ext.ComponentQuery.query('#gridViewId')[0];
gridView.setStore(store);
}
},
failure: function (result, request) {
console.log('api call was a failure');
},
scope: this
});
}
});
Now of course your data won't have "displayname, gender" etc.. but you should get the point.
I also found a working example here (I find it very sad that Sencha allows broken demos on their own website): http://demo.rasc.ch/eds/touch23/grid/grid/index.html

Sencha Touch 2 Load store crashs

Hello i have the following problem:
After i generate the AP and install it on my phone the requisition store.load breaks in this specific store called CHAMADOS, but when i close the app and restart, it does not crash and bring me all the informations in the list...
It seems that the .load requires bring me the informations in the first time.
When i close and open it again the cache informations required before is add to the list, but the load required on the restart APP does not work.
It crashs and dont add the items to the LIST, but the store has data because on restart it appears, i have others store in this app and they work fine!
On brownser its fine, the problem is in the APK
Here is the view
{
height: '60%',
ui:'round',
style:'padding:18px 0; background:#FFF;',
xtype: 'dataview',
id: 'feedListagemChamados',
store: 'Chamados',
itemTpl: '<span>{nom_chamado}</span> '
}
Here is the store
Ext.define('WE3Chamados.store.Chamados', {
extend: 'Ext.data.Store',
config: {
model: 'WE3Chamados.model.Chamado',
autoLoad: true,
proxy: {
type: 'jsonp',
url: 'http://LINK?cod_usuario='+localStorage.getItem("usuarioId"),
callbackKey: 'callback',
reader: {
type: 'json',
rootProperty : 'chamados',
successProperty: 'success'
}
}
}});
Here is where i call the store to load (CONTROLLER)
showListaChamados: function (direcao) {
this.cleanApp();
store = Ext.getStore('Chamados').load();
store.load({
scope : this,
callback : function(records, operation, success) {
***IT BREAKS HERE ON RETURN***
Ext.Msg.alert('Opps', records[0].data.nom_usuario, this);
Ext.Viewport.animateActiveItem(this.getChamadoView(), this.getSlideTransition(direcao));
}
});
Ext.Msg.alert('Opps', store.data, this);
}
Here is the model
Ext.define('WE3Chamados.model.Chamado', {
extend: 'Ext.data.Model',
config: {
fields: [
{
name: 'cod_chamado'
},
{
name: 'nom_chamado'
},
{
name: 'des_chamado'
},
{
name: 'cod_equipe'
},
{
name: 'dat_cadastro'
},
{
name: 'dat_previsao'
},
{
name: 'dat_necessaria'
},
{
name: 'num_prioridade'
},
{
name: 'cod_projeto'
},
{
name: 'nom_usuario'
},
{
name: 'cod_status'
},
{
name: 'nom_projeto'
},
{
name: 'des_equipe'
},
{
name: 'nom_status'
},
{
name: 'nom_cliente'
},
{
name: 'cod_usuario'
},
{
name: 'cod_usuario_responsavel'
}
]
}});
I found the problem, it was in the localStorage.getItem("usuarioId") its not sendind it by the get, because it is after login, i think there is a bug in the js or its so fast that the comand to send the link cant get the localStorage.getItem.
Im trying using php SESSION now.

Resources