PDA

View Full Version : Delete/Clear Local Storage record on Mobile Browser ?



trinitrotoluen
19 Feb 2011, 7:41 AM
Hi All,

On my pc I can delete/clear all local storage record from safari web inspector, but on my Android Mobile I don't have a clue how to do it, any suggestion ? thx

mitchellsimoens
19 Feb 2011, 6:34 PM
I think you can do is to clear all local storage


window.localStorage.clear()

You would have to google how to delete just one. If you are using LocalStorageProxy, it will not delete a record, it's a bug.

trinitrotoluen
26 Feb 2011, 7:40 AM
thanks mate, it work :)

Bucs
16 Mar 2011, 7:04 AM
Mitchell, just found your comment here on the localStorage deletion bug when trying to delete a single record. Have you found a workaround by chance, or know if there is a fix for this?

I just built a cart based on local storage, only to find out that I cannot remove an item :(

mitchellsimoens
16 Mar 2011, 7:05 AM
Mitchell, just found your comment here on the localStorage deletion bug when trying to delete a single record. Have you found a workaround by chance, or know if there is a fix for this?

I just built a cart based on local storage, only to find out that I cannot remove an item :(

Last I remember it was working IF you set your ID to int. I think. I will create a test script to test but I think that's what I found out.

Bucs
16 Mar 2011, 7:11 AM
You mean the id defined for the localstorage proxy? How will you be able to distinguish between multiple key/value pairs?

Currently, my id for the localstorage proxy is defined something like 'store-cart', and the records get stored with a key like 'store-cart-1, store-cart-2', etc.

Bucs
16 Mar 2011, 7:15 AM
Well, ok, I guess your records would just be stored as 100-1, 100-2, etc if I gave the proxy an id: 100.

However, I just tried and it still doesn't work. This is a major bummer :(

mitchellsimoens
16 Mar 2011, 7:31 AM
This worked 100% on Sencha Touch 1.0.1a, 1.0.2, and 1.1.0


Ext.regModel("CartModel", {
fields: [
{ name: "id", type: "int" }, //worked with type = "string"
{ name: "name", type: "string" }
]
});

var store = new Ext.data.Store({
autoLoad: true,
model: "CartModel",
proxy: {
type : "localstorage",
id : "cart-store"
}
});

store.add({
id: 1,
name: "Product 1"
});
store.add({
id: 2,
name: "Product 2"
});
store.sync();

setTimeout(function() {
console.log("Removing");
var rec = store.getAt(0);
store.remove(rec);
store.sync();
}, 2000);

There is still an issue and that's if you add records with the same id more than once to the store. If you add both Products like above and then try to add either of them without removing them first, you will see this:

cart-store-1 -> {"id":1,"name":"Product 1"}
cart-store-2 -> {"id":2,"name":"Product 2"}
cart-store -> 1,2,1,2

You can see the ids were added twice. And you will get an error. You can listen to the beforesync event to check if the id already exists and handle it.

Bucs
16 Mar 2011, 7:44 AM
Ok, thanks for this, I need to play with it and see what's up. I guess you meant the id or the record being added has to be an int, not the store id. Problem with that is that I am adding model instances to the store, and the model has an id of type guid (which is string in the JSON case). So I cannot change that id in the model to an int.

Seems as though the id in the added model and the localStorage array are not related though, or shouldn't be anyways, because when I add a model with the guid as the id, the counters are still incrementally set with integers, and the item key's still get that index appended to them.

Are we saying that your model id property must be an int so that the removeItem can find the key with that id? I sure hope not as that would still qualify as a major bug imo


Thanks for the efforts though.

mitchellsimoens
16 Mar 2011, 7:46 AM
I actually tried it with string as the type and it worked. Just needs to always be unique as if you add an id twice, it will just keep appending the id to the end of the cart-store key. If you remove a record that has multiple ids in that cart-store key, it will only remove one and the rest are now phantom ids.

mitchellsimoens
16 Mar 2011, 8:04 AM
Also, in the cart-store key, it holds a comma-delimited string of all the ids that is loaded into the store and synced with the proxy.

Bucs
16 Mar 2011, 8:15 AM
Hmmm, I am using 1.0.2 (didn't even know 1.1 was available) and it simply does not work as you describe for me for some reason.

Code in dataview itemtap listener is:


var ds = dv.getStore();
var rec = ds.getAt(index);
ds.remove(rec);
ds.sync();


The item gets removed from the DataView immediately, but never from the underlying localStorage.

Here is the model instance that is copied from the the 'store-cart-3' item value for the key 'store-cart-3':


{"Id":"4299189f-fa9a-4643-a5a3-34a5564b7398","Name":"Aphex Systems 120A Servo-Balanced Distribution Amplifier","Description":"","ShortDescription":"","CatalogUrl":"http://www.website.com/Mobile/TESTSITE/Audio-Equipment/Audio-Distribution/Aphex-Systems/APHEX-120A.xhtml","ThumbUrl":"http://www.website.com/Mobile/TestSite/productImage/75X75/APX-120A.JPG","MfgInfo":{"Name":"Aphex Systems","ProductListUrl":null,"LogoUrl":null},"BasePartNumber":"APX-120A","ListPrice":"$379.00","OurPrice":"$329.00","IsExclusive":false}

mitchellsimoens
16 Mar 2011, 8:25 AM
You are right. Tested in 1.1.0 and I get an error that it can't read the id property. Tried removing the '-' and still had error. It actually has nothing to do with removing, added a simple record with an id (type string) of "abcdef" and added it without removing and got an error. The id that get's passed gets converted to a int and so "abcdef" gets converted to NaN of course. This gets ugly in the framework I think.

Bucs
16 Mar 2011, 8:26 AM
Ok, well...the dealio is that the model REQUIRES a property of 'id' and it appears that localStorage will fill that property with a the counter that it appends on to the end of the key.

My model had a property of "Id", not 'id', so it apparently cannot make the association to perform the delete...which is strange considering that it is appending the counter to the key.

So, i simply added an "id" property to the model let localStorage give it a counter value. Now the prior code works just fine.

Not sure if this a bug or if it's by design. If the latter, then the APi docs should definitely mention this.

mitchellsimoens
16 Mar 2011, 8:36 AM
This override will allow you to remove a record from the proxy which has an id with letters.


Ext.override(Ext.data.WebStorageProxy, {
getIds: function() {
var ids = (this.getStorageObject().getItem(this.id) || "").split(","),
length = ids.length,
i;

if (length == 1 && ids[0] == "") {
ids = [];
}

return ids;
}
});

Tested by adding these records:


store.add({
id: "4299189f-fa9a-4643-a5a3-34a5564b7398",
name: "Product 1"
});
store.add({
id: "abcdef",
name: "Product 2"
});
store.add({
id: 1,
name: "Product 1"
});

Note the first record has an id that you provided earlier. If you don't have a field that has a name 'id' (case sensitive) then you can change that in your model:


Ext.regModel("CartModel", {
idProperty: "Id", //defaults to 'id'
....
});

It's not documented but it works. Now you won't have the counter, just will use the idProperty.

Bucs
16 Mar 2011, 8:53 AM
Did you try to the Delete with that? Doesn't work unfortunately. The item key does in fact get appended with the guid string, and the store key has the value of the guid...but the counter node is not created like you said. It doesn't seem to be able to make the association to make the delete again with that override.

Bucs
16 Mar 2011, 8:54 AM
Error is again "Cannot read property 'Id' of null".

Bucs
16 Mar 2011, 8:55 AM
And that was after changing my model to:


*/
Ext.regModel("Product", {
idProperty: "Id", //defaults to 'id'
fields: [
{ name: "Id", type: "string" },
{ name: "Name", type: "string" },


and used your override.

mitchellsimoens
16 Mar 2011, 8:59 AM
Tried with 1.0.2 and 1.1.0 and it adds and deletes correctly. Entire JS code:


Ext.override(Ext.data.WebStorageProxy, {
getIds: function() {
var ids = (this.getStorageObject().getItem(this.id) || "").split(","),
length = ids.length,
i;

if (length == 1 && ids[0] == "") {
ids = [];
}

return ids;
}
});

Ext.setup({
tabletStartupScreen: 'tablet_startup.png',
onReady: function() {

Ext.regModel("CartModel", {
idProperty : "Id",
fields : [
{ name : "Id", type : "string" },
{ name : "name", type : "string" }
]
});

var store = new Ext.data.Store({
autoLoad : true,
model : "CartModel",
proxy : {
type : "localstorage",
id : "cart-store"
}
});

store.add({
Id : "4299189f-fa9a-4643-a5a3-34a5564b7398",
name : "Product 1"
});
store.add({
Id : "abcdef",
name : "Product 2"
});
store.add({
Id : 1,
name : "Product 1"
});
store.sync();

setTimeout(function() {
console.log("Removing");
var rec = store.getAt(0);
store.remove(rec);
store.sync();
}, 2000);


}
});

Bucs
16 Mar 2011, 9:01 AM
Ok, I'll give this another shot after lunch. Thanks again for all your help Mitchell.

Bucs
16 Mar 2011, 11:51 AM
Still doesn't work for me. Are you looking at the Chrome localStorage and the store key in particular after the initial add, then again after the remove?

After the add I get the following:


key: cart-14ad39d4-261f-44c8-8319-d12eab14ea4a
value: {"Id":"14ad39d4-261f-44c8-8319-d12eab14ea4a",....}


Then after the Remove I have:


key: cart
value: 14


So, when using the long strings, i.e. guids, it's hacking off the guid at the first nonnumeric number and leaving that in the store key orphaned without a record, which breaks the store if you've bound something to it. Also leaving a bunch of NaN in the store key, almost as if the parsing is getting messed up by the "-" in the guid.

mitchellsimoens
16 Mar 2011, 1:23 PM
Video of what I get:


http://www.simoens.org/videos/LocalStorage%20Removal.mp4

This is the code, updated override to make sure ids don't get duplicated and added buttons to add/remove:


Ext.override(Ext.data.WebStorageProxy, {
getIds: function() {
var ids = (this.getStorageObject().getItem(this.id) || "").split(","),
length = ids.length,
i;

if (length == 1 && ids[0] == "") {
ids = [];
}

var idArray = [];
for (var i = 0; i < ids.length; i++) {
var id = ids[i];
if (idArray.indexOf(id) < 0) {
idArray.push(id);
}
}

return idArray;
}
});

Ext.setup({
tabletStartupScreen: 'tablet_startup.png',
onReady: function() {
new Ext.Button({
renderTo : Ext.getBody(),
text : "Load Records",
handler : function() {
store.add({
Id : "4299189f-fa9a-4643-a5a3-34a5564b7398",
name : "Product 1"
});
store.add({
Id : "abcdef",
name : "Product 2"
});
store.add({
Id : 1,
name : "Product 1"
});
store.sync();
}
});
new Ext.Button({
renderTo : Ext.getBody(),
text : "Delete Record",
handler : function() {
var rec = store.getAt(0);
store.remove(rec);
store.sync();
}
});

Ext.regModel("CartModel", {
idProperty: "Id",
fields: [
{ name: "Id", type: "string" }, //worked with type = "string"
{ name: "name", type: "string" }
]
});

var store = new Ext.data.Store({
autoLoad: true,
model: "CartModel",
proxy: {
type : "localstorage",
id : "cart-store"
}
});


}
});

Bucs
16 Mar 2011, 2:08 PM
a) I'm an *****...it helps when you include the ".js" when referencing the overrides.js file. Was never getting called :(
b) All works like a champ now
c) Going to be testing your accordion next week I think...I need it in a big way.
d) Where I do vote for you for MVP of the Touch forums? :)

Thanks again, localStorage is awesome when it actually works right. I would push Sencha to move this override into production!

basty
1 Jun 2011, 1:43 AM
I'm a little bit confused about the "mylocalstorage-counter" value, because its not reset to 0 on sync if there are no more items in the store (testet in Google Chrome Developertools).

To reproduce: I added 3 items to my store with the LocalStorage proxy. Then I called store.sync() and I could see the 3 items in the Developertools. After removing the last item from the store with store.removeAt(id); and calling store.sync() again, all items are removed from the localstorage (thats OK so far), but the "mylocalstorage-counter" field contains still the number 3.

Can someone else see it too? It hasn't an effect on the running programm, but I think the counter should work right for the case you need the correct counter-value.

PS: I'm using the version 1.1.0

yanhsy
3 Jan 2012, 6:35 AM
This works fine!



localStore.getProxy().clear();