getProperty
and setProperty
internallysetProperty
and getProperty
to first check the localStorage, the model + binding functionality itself will do all of the heavy lifting for me. Nifty? Yes. Easy? Also yes.constructor: function(data, aFieldsToRetain) {
this._fieldToRetain = aFieldsToRetain || [];
this._storage = Storage;
if (!(this._fieldToRetain instanceof Array))
throw new Error(
"Fields to retain for local storage needs to be an array"
);
//good old constructor call to set the data
JSONModel.prototype.constructor.call(this, data);
},
fieldsToRetain
array. This will contain a list of properties that you'd like to be stored. After that, the normal constructor is called.Storage
is the window.localStorage
object, I figure I'd abstract it out in case I want to switch to cookies, sessionStorage, or maybe something from Cordova / PhoneGap / Mobile services. You never know!setProperty: function(param, value) {
if (this._fieldToRetain.indexOf(param) >= 0) {
const toStore = typeof value === 'object' ? JSON.stringify(value) : value;
this._storage.setItem(this._getLocalStorageParamName(param), toStore);
}
JSONModel.prototype.setProperty.call(this, param, value);
},
_getLocalStorageParamName: function(param) {
return `myapp${param}`;
}
_getLocalStorageParamName
is a convenience method to generate a more unique identifier. I use the logged in userID and the application name from the manifest myself, don't want to run into trouble between different apps (launchpad, I'm looking at you).localStorage.setItem
.toString
which means you'll end up with [Object object]
and 1,2,3
instead of your object or array.getProperty: function(param) {
var prop = this._storage.getItem(this._getLocalStorageParamName(param)) ||
JSONModel.prototype.getProperty.call(this, param)
var value;
//JSON.parse can actually crash, so the try/catch block is justified
try {
value = JSON.parse(prop);
} catch (e) {
value = prop;
}
return value;
},
JSON.parse
crashes when fed rubbish, so if that call fails it was not stringified and we'll return it the way it was.const fieldsToRetain = ["/name"];
let model = new LocalstorageJSONModel({
name: 'Jorg',
country: 'Australia'
}, fieldsToRetain);
name
forever and reload it when requested. If someone enters Jane
in the name field, the next time the app is opened the name Jane
appears regardless of how it's initialised.sap.ui.model.Filter
objects for instance since I seem to be using that a lot. Added bonus is that, without the fieldsToRetain
object it's just a JSONModel, so I turned it into a library and use it for everything. If you want to get rid of it again, change the import in the definition and it's like nothing ever happened.sap.ui.define(["sap/ui/model/json/JSONModel", "./Storage"], function(
JSONModel,
Storage
) {
"use strict";
return JSONModel.extend("demo.LocalstorageJSONModel", {
_fieldToRetain: false,
/*
constructor still takes the data object, but also an array of fields
to remember.
*/
constructor: function(data, aFieldsToRetain) {
this._fieldToRetain = aFieldsToRetain || [];
this._storage = Storage;
if (!(this._fieldToRetain instanceof Array))
throw new Error(
"Fields to retain for local storage needs to be an array"
);
//good old constructor call to set the data
JSONModel.prototype.constructor.call(this, data);
},
//redefine the getProperty method. Before the JSON model loads it's own content, I want
//to see what's inside the localstorage, and I'd like to parse it if it's JSON
getProperty: function(param) {
var prop = this._storage.getItem(this._getLocalStorageParamName(param)) ||
JSONModel.prototype.getProperty.call(this, param)
var value;
//JSON.parse can actually crash, so the try/catch block is justified
try {
value = JSON.parse(prop);
} catch (e) {
value = prop;
}
return value;
},
//convenience method. sometimes you just want to clear all variables.
clearStorage: function() {
this._storage.clear();
},
//redefine setProperty to first check if the field is in the fields to retain.
//in that case, send it to localstorage as well as do the parent method.
setProperty: function(param, value) {
if (this._fieldToRetain.indexOf(param) >= 0) {
const toStore = typeof value === 'object' ? JSON.stringify(value) : value;
this._storage.setItem(this._getLocalStorageParamName(param), toStore);
}
JSONModel.prototype.setProperty.call(this, param, value);
},
//you should create unique identifiers. in productive apps this needs more consideration. i use
//app id from the manifest and user ID.
_getLocalStorageParamName: function(param) {
return `myapp${param}`;
}
});
});
sap.ui.define([], function() {
return window.localStorage;
});
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
13 | |
9 | |
7 | |
7 | |
5 | |
5 | |
4 | |
4 | |
3 | |
3 |