How do I update localStorage items? - javascript

I'm having a problem where the cached object doesn't resemble the correct data so I figured it I can push up the most uptodate version to the browser cache it will solve my problem.
How do you update your localStorage with a new object? So if I had a controller with that had an assessment updated. How can I push that assessment object up to the localStorage?

To do that with native JavaScript, you would do something like this:
localStorage.setItem('itemKey', JSON.stringify(yourObject));
var item = JSON.parse(localStorage.getItem('itemKey'));
Within the context of angular, you should make a localStorage service as a wrapper around localStorage and inject it into your service or controller. Or you could inject $window and use it directly off of that like: $window.localStorage

A response specifically for the asker of this duplicate question:
LocalStorage can only store strings, which is why you're stringifying your object before storing it. To manipulate the stored string as an object, you can pass it to JSON.parse (assuming it's properly JSON-formatted). Then to store the modified version, you need to convert it back into a string.
// Creates JSON-formatted object, converts it to a string and stores the string as "ship"
const ship = { name: "black pearl", captain: "Jack Sparrow" };
const originalStringifiedForStorgage = JSON.stringify(ship);
localStorage.setItem("ship", JSON.stringify(ship));
// Retrieves the string and converts it to a JavaScript object
const retrievedString = localStorage.getItem("ship");
const parsedObject = JSON.parse(retrievedString);
// Modifies the object, converts it to a string and replaces the existing `ship` in LocalStorage
parsedObject.name = "newName";
const modifiedndstrigifiedForStorage = JSON.stringify(parsedObject);
localStorage.setItem("ship", strigifiedForStorage);

If the object is in JSON format (not sure if Angular uses a different format) you could probably use the setItem() and getItem() methods to update and retrieve local storage items!
For example taken from the following post:
http://thejackalofjavascript.com/storing-objects-html5-local-storage/
var me = {name:'myname',age:99,gender:'myGender'};
localStorage.setItem("user",me);
//fetch object
console.log(localStorage.getItem("user")); // will return "[object Object]"

You can use full featured Angular module angular-local-storage
An AngularJS module that gives you access to the browsers local
storage with cookie fallback
set
myApp.controller('MainCtrl', function($scope, localStorageService) {
//...
function submit(key, val) {
return localStorageService.set(key, val);
}
//...
});
get
myApp.controller('MainCtrl', function($scope, localStorageService) {
//...
function getItem(key) {
return localStorageService.get(key);
}
//...
});

setItem wont work instead it will create another item in localStorage with the same name
Instead directly use
localStorage.item = (what ever the change that you want in the item)

Related

Sending a list of custom objects from server to client

I made a Character class shared by the client and server in the same js file.
The server instanciates these characters and stocks them in a characterList object. I send it to the client with socket.emit( 'updated_characters', characterList ), but the client gets back an object of Object, instead of an object of Character, so I can't use my Character's methods on them.
How can I get around that ?
You can't send custom object types directly using socket.io. socket.io uses JSON as the transport format for objects and JSON does not have the ability to record or rebuild custom object types.
So, what you need to do is to create a serialized format for your objects (which will also likely be JSON) and then when you read the data on the other end, you will construct a custom object in your own code and then pass it this data in the constructor from which it will initialize itself.
The canonical ways to do this is to create a serialize method for your custom object that creates a new plain object that contains all the relevant info that needs to be sent over the wire and does not contain references to other objects (since that can't be serialized). Keep in mind that objects often have housekeeping information that does not necessarily need to be sent to the other end. Then, create an initialize method for your custom object that can take this serialized data and properly initialize your object that you can use on the other end.
Here's a simple example:
function MyObject(data) {
if (data) {
this.init(data);
} else {
this.count = 0;
this.greeting = "hello"
}
}
MyObject.prototype = {
init: function(data) {
this.greeting = data.greeting;
this.count = data.count;
},
getData: function() {
return {greeting: this.greeting, count: this.count};
},
talk: function() {
say(this.greeting);
}
};
Then, on the sending end of things, if you have an instance of your object in item, you would send the data with:
socket.emit('updated_characters', item.getData());
And, on the receiving side of things, you would have this:
socket.on('updated_characters', function(data) {
var item = new MyObject(data);
// do something with the item here
});
socket.emit( 'updated_characters', JSON.stringify(characterList) );
we have to do JSON.stringify in order for socket to identify as JSON and display it in front-end

What is the benefit of angular.copy?

I use angular.copy in some cases, like copying model default values to the form model, like this:
var customerModel = {
name: '',
point: 0
};
$scope.customer = angular.copy(customerModel);
function save() {
//... Reset $scope.customer after success submit
$scope.customer = angular.copy(customerModel);
}
... to prevent the default customerModel changed.
But why copy empty object or array? {} or []
I found in some codes used angular.copy on empty object or array. Why they don't assign empty object directly to the variable?
$scope.customer = {}; // or [] for array
If you use copy on empty object or array, could you explain the benefit?
What about ajax response ($http)?
And one more question, what did you do to ajax response? copy or assign it directly to a variable?
$http
.get('example.com/api/v1/get/customer/1')
.success(function(response) {
$scope.customer = angular.copy(response.data);
// or do you use $scope.customer = response.data ?
})
;
And if you used copy, what do you think happened to the response object?
Is it remain in the memory? or deleted automatically?
You copy an object to prevent other code from modifying it. (original object might change, but your copy won't see the changes)
If you were to do this:
$scope.customer = customerModel
... and some callback/service/whatnot changed customerModel, your scope would reflect this change. This is not always desirable, hence the need for deep copying.
Copying empty literal object
$scope.customer = angular.copy({})
// or
$scope.customer = {}
This doesn't make any difference. It's a new empty object every time. Note that it's very different from this:
this.customerModel = {};
$scope.customer = angular.copy(this.customerModel)
Copying ajax response data
Same rules apply. If you want to ensure that this object doesn't change from underneath you (which may happen if you also passed it to somewhere else, for example), you should copy it.
angular.copy creates deep copy of variable so that it would hold the reference of another variable
sometimes it happens when user dont want to use call by reference then deep copy comes in action According to your question
var customerModel = {
name: '',
point: 0
};
If you will use $scope.customer = angular.copy(customerModel); it will create deep copy of customerModel
As far as $http Service is concerned .Data is coming from response and If you you will assign It directly then there would be no effect of call by reference because data is coming from another source.
So I would rather assign it directly in case of $http.get()

Best way of getting the key after $add

I am using angularFire v 0.5.0
On my returned object I do a $add.
What would be the best way to get the generated key?
It must be something in the succes callback of the $add, because the key will come back asynchrounlusly?
scope.settings = $firebase(ref);
scope.settings.value = {
vat: {
inclusive: true
}
}
}
scope.settings.$add (scope.settings.value).then( function ( {
scope.settings.key = ???
});
note: this is not the actual code, this is just to clarify the problem.
The actiual code is inside a factory in the loaded event, and there is a check if there is already a settings object inside the database.
This somewhat strange construct is to make it easyer for consumers of the factory to change the settings. The settings is a singleton. AngularFire does not return a array of objects, but every item is a object in the settings, with its own key.
$add returns a Firebase ref. Call name() on that ref.
scope.settings.$add(…).name();
See https://github.com/firebase/angularFire/blob/master/angularfire.js#L127.
from the angularfire docs:
The $add method takes a single argument of any type. It will append this value as a member of a list (ordered in chronological order). This is the equivalent of calling push(value) on a Firebase reference.
from the firebase docs (about push()):
Returns
A Firebase reference for the generated location.
so, i think the "key" that you want is the return value of the $add.
Maybe they've changed it in newer versions, now it works like this:
$add() will return a promise. You have to use the callback which runs on success. For example:
var something = $scope.somethings.$add({name: "foo"});
something.then(function(e) {
console.log(e.name())
});
This allows you to perform different actions based on the outcome of the save/write attempt to Firebase.

Get row data from dojo store

I have this javascript of code
var store;
function dataBind(servletPath){
store = Observable(Cache(JsonRest({target:servletPath}), Memory()));
}
The servletPath will return me a json string that looks like this.
[{"colNo":1,"colMemberId":108}]
Lets say I call this javascript function and it returns a record to me. How do I get the "colMemberId" from the store?
If your function returns a Dojo store object then you can access it's contents through the use of it's query() function like so
var store;
function dataBind(servletPath){
return store = Observable(Cache(Memory({data:[{"colNo":1,"colMemberId":108}]}), Memory()));
}
console.log("store: ", dataBind().query({}));
Calling the query function with an empty object as a parameter will return an array containing the entire contents of the store.
Documentation: http://dojotoolkit.org/reference-guide/1.10/dojo/store/Memory.html
Here is a jsFiddle example : http://jsfiddle.net/kagant15/y7ec4byk/4/

Use $scope as json data with the $http service

I want to post everything that's on angular's scope service, its not much in my case but I don't want to create another object:
var model = angular.toJson($scope);
$http.post('/myUrl', model)
.success(function(data) {
});
However, it looks like $scope is a circular structure, because you can tell via: Converting circular structure to JSON when I use JSON.stringify or the string literal $Scope when I use the sample above.
Is there anyway to capture all of this data off of $scope?
This is my current hack, using underscore and underscore.string:
var toJs = function(item) {
var obj = {};
_.each(item, function(val, key) {
if (!_s.startsWith(key,'$')) {
obj[key] = val;
}
});
return obj;
};
then just passing:
toJs($scope)
You don't want to create new object, so a possible dirty solutions is to remove the circular reference and every other property you don't want to POST from $scope, call toJson, then put all previously deleted properties back to $scope.
Nest a child property on $scope and call toJson on that.
<input ng-model='email'>
becomes
<input ng-model='user.email'>
so that
$http.post('/url', angular.toJson($scope.user));

Categories