Save key=>value style with ngStorage/localstorage - javascript

In my Ionic app I've added the plugin 'ngStorage' and it comes with a little demo code:
var add = function (thing) {
$localStorage.things.push(thing);
}
This works exactly as told. I add("foo") it, and do getAll() and the value is there. I remove the add(), but keep the getAll(), I still have the value "foo" (as expected).
This isn't very usefull for me, I want to access it with keys, so I've made the following:
var addByKey = function (key, value) {
$localStorage.things[key] = value;
// Or, I've also tried:
$localStorage.things.key = value;
}
When I do the addByKey("foo","bar") and then the getAll() I get the values exactly as I want. When I remove the addByKey() and reload, I expect it to still remember the set information, but it doesn't exist. However, the first attempt via the add() function still exists, "foo" is still there (meaning the array doesnt reset).
How do I make a key->value type of structure?
In case it's usefull:
.factory ('StorageService', function ($localStorage) {
$localStorage = $localStorage.$default({
things: []
});
var _getAll = function () {
return $localStorage.things;
};
var _add = function (thing) {
$localStorage.things.push(thing);
}
var _addByKey = function (thing, value) {
$localStorage.things[key] = value;
// Or, I've also tried:
$localStorage.things.key = value;
}
return {
getAll: _getAll,
add: _add,
addByKey: _addByKey
};
})

Assuming that you want a key value storage system you can simply use an object instead of an array so that every key can be set as a property of this object.
.factory('StorageService', function($localStorage) {
$localStorage = $localStorage.$default({
things: {}
});
var _getAll = function() {
return $localStorage.things;
};
var _addByKey = function(thing, value) {
$localStorage.things[thing] = value;
}
return {
getAll: _getAll,
addByKey: _addByKey
};
})
However, assuming that you want to keep a reference of all values on the main collection and access them through keys, you can consider using an object to store the things intead of an array. So that you can use a property to store all items (you can store in a different place as well) and use this object to store your keys by referencing the to a desired value on your collection.
You may need to implement the deletion logic to maintain the consistence between the collection and the dictionary.
Your factory would look like this:
.factory('StorageService', function($localStorage) {
$localStorage = $localStorage.$default({
things: {
items: []
}
});
var _getAll = function() {
return $localStorage.things.items;
};
var _add = function(thing) {
$localStorage.things.items.push(thing);
}
var _addByKey = function(thing, value) {
var i = $localStorage.things.items.push(value) - 1;
$localStorage.things[thing] = $localStorage.things.items[i];
}
return {
getAll: _getAll,
add: _add,
addByKey: _addByKey
};
})

Related

Understand JSON result

In my code I have to analyse JSON objects. I use a small function set:
visit = function(object) {
if (isIterable(object)) {
forEachIn(object, function (accessor, child) {
visit(child);
});
}
else {
var value = object;
console.log(value);
}
};
forEachIn = function(iterable, functionRef) {
for (var accessor in iterable) {
functionRef(accessor, iterable[accessor]);
}
};
isIterable = function(element) {
return isArray(element) || isObject(element);
};
isArray = function(element) {
return element.constructor == Array;
};
isObject = function(element) {
return element.constructor == Object;
};
If I throw now a JSON Object to the visit function, it give me just the value to the console. But I expected the key/value combination. Example:
Code throw
aa03ddbffe59448fb8a56f6b80e650053
But I expect
uuid: aa03ddbffe59448fb8a56f6b80e650053
Is there anything I misunderstand?
I think the value variable must contain a different type from what you're expecting. You could try putting a breakpoint on that line of code and inspecting the object to check what it is. You're expecting the value variable to contain an object with a single uuid property, but it looks to me like the variable actually just contains a string.

JavaScript constructor listen for this variable change

I'm creating a JavaScript object, and would like to be able to reactively detect changes in a passed in object.
I've tried to use Proxy objects, but have been unable to reproduce the desired behavior. An example I tried to implement into my code was this: Listening for variable changes in JavaScript
Here is the very basic shell of the constructor I am using:
function Fluid(options) {
this.options = options;
// Here is where I use the options object, and would like to be able to re-evaluate certain pieces of code if any values in 'this.options' changes.
}
let myApp = new Fluid({
testValue: 1
});
My expected output could be something like this:
function Fluid(options) {
this.options = options;
function doThings() {
if(this.options.testValue === 1) {
console.log("The value is 1");
} else {
console.log("The value is not 1");
}
}
doThings();
// Here I would implement the code to detect changes in the this.options object, and if this.options changes, I can execute a function, like doThings()
}
let myApp = new Fluid({
testValue: 1
});
// Console: The value is 1
myApp.testValue = 2;
// Console: The value is not 1
After expirimenting more the Proxy objects, I was able to fix this problem by using the following code:
function Fluid(options) {
this.options = options;
let proxyHandler = {
set: (target, objectKey, value) => {
console.log(`Setting property "${objectKey}" = "${value}"`);
return target[objectKey] = value;
}
};
this.options = new Proxy(this.options, proxyHandler);
}

call user function in foreach loop

i have understand that i need to change the global scope of this, because in the loop this refers to the window object. But if i try to define a variable in my foreach loop via a function its not working and i dont know why although my functio returns the correct value :(
// simple class for xml import
function io() {
this.vertexes = [];
this.getVertexByID = function(id) {
this.vertexes.forEach(function(entry) {
if (id == entry.id) {
// correct element found, displayed and returned
console.log(entry);
return entry;
}
});
}
this.importXML = function(xmlString) {
cells = this.xmlToJson(xmlString);
var parent = graph.getDefaultParent();
var _this = this;
graph.getModel().beginUpdate();
try {
// addEdges
cells.XMLInstance.Edges.Relation.forEach(function(entry) {
// both will be empty but i dont understand why :(
fromVertex = _this.getVertexByID(entry.fromNode);
toVertex = _this.getVertexByID(entry.toNode);
var e1 = graph.insertEdge(parent, null, '', fromVertex, toVertex);
});
} finally {
graph.getModel().endUpdate();
}
}
Returning a value in a forEach callback has no effect. It certainly is not the return value of the function that the forEach is part of.
So change this:
this.vertexes.forEach(function (entry) {
if(id==entry.id){
//correct element found,displayed and returned
console.log(entry);
return entry;
}
});
to this:
return this.vertexes.find(function (entry) {
return id==entry.id;
});

Constructing object to have a constructor method containing a set property method

I'm trying to make an object as a mock to pass into a test.
I don't know if I'm constructing it correctly - I'm getting Error: User() method does not exist.
injectedUser = {
set: function(key, val){
this[key] = val;
}
};
injectedParse = {
Parse: {
User: function() {
return injectedUser;
}
}
};
Parse = function() {
return injectedParse;
};
The desired behavior I'm looking for is for function Parse.User to be called with user = new Parse.User and be able to do user.set("key", "value");
But it seems like I'm not building this object properly? I have another issue but since it is more a javascript thing potentially, I made a new, more general issue about building objects
I also tried
set = function (key, val) {
this[key] = val;
}
mockParse = function(){
this.User()
};
mockParse.prototype.User = function(){
return set
};
$provide.value('Parse', mockParse);
That gave me the same error.
All the information you should know about constructing objects are at: http://ericleads.com/2013/02/fluent-javascript-three-different-kinds-of-prototypal-oo/

Class-type object not returning values across module in node.js

I am writing a simple application in node, but having trouble with referencing objects from different modules. The object constructor and methods are (I skipped some methods to keep the excerpt short):
function Account (name, password) {
this._name = name;
this._password = password;
this._attributes = [];
}
Account.prototype.load = function (id) {
var self = this;
self = db.loadObject(id, 'account'); // separate module to save/retrieve data
this._name = self._name;
this._password = self._password;
this._attributes = self._attributes;
return this;
};
Account.prototype.getAttributes = function () {
return this._attributes;
}
Account.prototype.addAttributes = function (a) {
this._attributes.push(a);
};
module.exports = Account;
The db module is nothing fancy at this point:
var fs = require('fs');
var paths = {
'account' : './data/accounts/'
};
function loadObject (name, type) {
var filePath = paths[type] + name + '.json';
if (!fs.existsSync(filePath)) {
return false;
}
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
};
function saveObject (object, type) {
fs.writeFileSync(paths[type] + object.getName() + '.json', JSON.stringify(object),'utf8');
};
exports.loadObject = loadObject;
exports.saveObject = saveObject;
The file is saved as:
{"_name":"John","_password":"1234","_attributes":[["Jane","sub",[[10,1]]]]}
On my caller module I attempt to retrieve the attributes:
var Account = require('./account.js');
var account = new Account();
...
account.load(name);
...
var attr = account.getAttributes();
for (var item in attr) {
console.log(item[0]);
};
...
In the code above, the last loop prints undefined objects. I have checked the files and the information is saved and loaded without any problems. The array attr is not empty. If I print it with:
util.log(typeof attr+': '+attr);
I get:
object: Jane,sub,10,1
Instance issue? Should I rewrite the _attributes to be accessed directly via account.attributes?
This is the code you currently have for outputting your data:
var attr = account.getAttributes();
for (var item in attr) {
console.log(item[0]);
};
What this code does is output to the console the first character of each key in your _attributes field. With the data you've shown in your question, what this outputs is 0 because your _attributes field has this value: [["Jane","sub",[[10,1]]]]. When used in var item in attr the item variable will get only one value the string "0", and item[0] will also evaluate to the string "0". I've actually cut and pasted your code and data into files and ran your code to double check this and this is indeed what I get when I run the code. I don't get undefined values. A more sensible way to get the values out of the array would be:
var attr = account.getAttributes();
for (var item in attr) {
console.log(attr[item]);
}
If you want to iterate two levels deep:
for (var item in attr) {
var value = attr[item];
for (var item2 in value) {
console.log(value[item2]);
}
}

Categories