AngularJS: Persistent Error with $sessionStorage - angularjs

I am trying to store the count of the score using $sessionStorage, for some reason, the assignment operation. Also, I cannot assign $sessionStorage variable with anything else as well.
$sessionStorage.score = parseInt($sessionStorage.score) + 1;//gives error
$scope.x = 0;
$sessionStorage.score = $scope.x; // also gives error
Also,
$sessionStorage.score = JSON.stringify($scope.x);// gives error
how to resolve this?

Use "sessionStorage" instead of "$sessionStorage".

Related

modifying object in componentDidMount() [duplicate]

I’ll start with the code:
var s = ["hi"];
console.log(s);
s[0] = "bye";
console.log(s);
Simple, right? In response to this, the Firefox console says:
[ "hi" ]
[ "bye" ]
Wonderful, but Chrome’s JavaScript console (7.0.517.41 beta) says:
[ "bye" ]
[ "bye" ]
Have I done something wrong, or is Chrome’s JavaScript console being exceptionally lazy about evaluating my array?
Thanks for the comment, tec. I was able to find an existing unconfirmed Webkit bug that explains this issue: https://bugs.webkit.org/show_bug.cgi?id=35801 (EDIT: now fixed!)
There appears to be some debate regarding just how much of a bug it is and whether it's fixable. It does seem like bad behavior to me. It was especially troubling to me because, in Chrome at least, it occurs when the code resides in scripts that are executed immediately (before the page is loaded), even when the console is open, whenever the page is refreshed. Calling console.log when the console is not yet active only results in a reference to the object being queued, not the output the console will contain. Therefore, the array (or any object), will not be evaluated until the console is ready. It really is a case of lazy evaluation.
However, there is a simple way to avoid this in your code:
var s = ["hi"];
console.log(s.toString());
s[0] = "bye";
console.log(s.toString());
By calling toString, you create a representation in memory that will not be altered by following statements, which the console will read when it is ready. The console output is slightly different from passing the object directly, but it seems acceptable:
hi
bye
From Eric's explanation, it is due to console.log() being queued up, and it prints a later value of the array (or object).
There can be 5 solutions:
1. arr.toString() // not well for [1,[2,3]] as it shows 1,2,3
2. arr.join() // same as above
3. arr.slice(0) // a new array is created, but if arr is [1, 2, arr2, 3]
// and arr2 changes, then later value might be shown
4. arr.concat() // a new array is created, but same issue as slice(0)
5. JSON.stringify(arr) // works well as it takes a snapshot of the whole array
// or object, and the format shows the exact structure
You can clone an array with Array#slice:
console.log(s); // ["bye"], i.e. incorrect
console.log(s.slice()); // ["hi"], i.e. correct
A function that you can use instead of console.log that doesn't have this problem is as follows:
console.logShallowCopy = function () {
function slicedIfArray(arg) {
return Array.isArray(arg) ? arg.slice() : arg;
}
var argsSnapshot = Array.prototype.map.call(arguments, slicedIfArray);
return console.log.apply(console, argsSnapshot);
};
For the case of objects, unfortunately, the best method appears to be to debug first with a non-WebKit browser, or to write a complicated function to clone. If you are only working with simple objects, where order of keys doesn't matter and there are no functions, you could always do:
console.logSanitizedCopy = function () {
var args = Array.prototype.slice.call(arguments);
var sanitizedArgs = JSON.parse(JSON.stringify(args));
return console.log.apply(console, sanitizedArgs);
};
All of these methods are obviously very slow, so even more so than with normal console.logs, you have to strip them off after you're done debugging.
This has been patched in Webkit, however when using the React framework this happens for me in some circumstances, if you have such problems just use as others suggest:
console.log(JSON.stringify(the_array));
Looks like Chrome is replacing in its "pre compile" phase any instance of "s" with pointer to the actual array.
One way around is by cloning the array, logging fresh copy instead:
var s = ["hi"];
console.log(CloneArray(s));
s[0] = "bye";
console.log(CloneArray(s));
function CloneArray(array)
{
var clone = new Array();
for (var i = 0; i < array.length; i++)
clone[clone.length] = array[i];
return clone;
}
the shortest solution so far is to use array or object spread syntax to get a clone of values to be preserved as in time of logging, ie:
console.log({...myObject});
console.log([...myArray]);
however be warned as it does a shallow copy, so any deep nested non-primitive values will not be cloned and thus shown in their modified state in the console
This is already answered, but I'll drop my answer anyway. I implemented a simple console wrapper which doesn't suffer from this issue. Requires jQuery.
It implements only log, warn and error methods, you will have to add some more in order for it to be interchangeable with a regular console.
var fixedConsole;
(function($) {
var _freezeOne = function(arg) {
if (typeof arg === 'object') {
return $.extend(true, {}, arg);
} else {
return arg;
}
};
var _freezeAll = function(args) {
var frozen = [];
for (var i=0; i<args.length; i++) {
frozen.push(_freezeOne(args[i]));
}
return frozen;
};
fixedConsole = {
log: function() { console.log.apply(console, _freezeAll(arguments)); },
warn: function() { console.warn.apply(console, _freezeAll(arguments)); },
error: function() { console.error.apply(console, _freezeAll(arguments)); }
};
})(jQuery);

Easy about Angular: Why does it change order?

Just a 'silly' question but it's confusing me a lot, for a student of AngularJS.
When console.logging a variable, let's say var result is a promise from a GET or whatever, and .then() I do some tasks, like asignin a variable.
var result = ... ;
$scope.number = {};
result.then(function(data) {
$scope.number = 5;
console.log($scope.number);
});
console.log($scope.number);
Okay!
So to me, this should print
5
5
(In case I initialise a $scope variable, outside this function or promise)
5
undefined
(in case the second .log tries to print a non-defined global variable, outside the function)
So I get:
undefined
5
Why does the outter $scope.number print before the inner (5) variable?
I want to initialise the variable after getting the GET, within the promise, and later on, use the initialised var.
Thank you =) This will speed up my learning!
The main thing to understand is that the following returns a promise immediately:
var result = ... ;
Right after that, you pass a function to the .then method of the promise:
result.then(...)
And right after that you do:
console.log($scope.number);
Then later - once the asynchronous action (like an HTTP request) completes and the promise resolves - the function you passed to .then finally executes:
function(data) {
$scope.number = 5;
console.log($scope.number);
}
So promises exist to help you manage asynchronous behavior. They really start to shine when you have to manage multiple asychronous functions:
asyncFunction1().then(function() {
// This executes after asyncFunction1 completes
return asyncFunction2();
}).then(function() {
// This executes after asyncFunction2 completes
});

AngularJS $parse/scope.$eval expression

I am trying to use $parse to get my required result.
Here is my Example. Check script.js file
I want to parse an expression but I am getting error. How can I solve this kind of data?
Here is my code
scope.data = {name:{_en:"username", _ar:'مفقود '}}
// set variable in scope like scope.name_en = scope.data._en, scope.name_ar = scope.data._ar
for(var i in scope.data) for(var j in scope.data[i]) scope[i+j] = scope.data[i][j];
scope.messages2 = [{code:200, msg_en:"{{name_en}} is missing.", msg_ar:"مفقود {{name_ar}}"}];
scope.finalMegs = [];
for( var i in scope.messages2) {
var obj = {};
for(var j in scope.messages2[i]){
if(j == 'code') continue;
console.log(scope.$eval(scope.messages2[i][j]) );
obj[j] = $parse(scope.messages2[i][j])
}
/*
required object is {msg_en = "username is missing.", msg_ar:"مفقود مفقود "}
*/
scope.finalMegs.push(obj);
}
console.log(scope.finalMegs);
Thank you.
Syntax of your messages is incorrect, so the messages can't be parsed by $parse or $eval. You should write them in this format:
scope.messages2 = [
{
code:200,
msg_en:"name_en + ' is missing.'",
msg_ar:"'مفقود ' + name_ar"
}
];
Then if you want to get object with already formatted messages you should call $parse function in this way:
obj[j] = $parse(scope.messages2[i][j])(scope);
Because $parse converts angular expression to function, which you should call with your scope to get expected results.
But in your case, I think that you can replace those line to this also:
obj[j] = scope.$eval(scope.messages2[i][j]);
Result will be the same.
Example on plunker. (I've reformatted your example a little bit)
Please, take a look also at the example of usage scope.$eval here and documentation about $parse.

Error while using removeChild() and accessing members of array

I am stuck doing this even though I know it's very simple. Yet, I am getting errors.
What I have:
I have 3 arrays.
1st Array contains objects of UpgradeButton class.
2nd Array contains objects of BuyButtonclass.
3rd Array named newCostlyShops contains Numbers.
BuyButton class and UpgradeButton class, both have a shopCode member which is a number; the number which I'm trying to equate.
What I'm trying to do:
My goal is to first look for BuyButton and UpgradeButton objects in the respective arrays which have shopCodes same as those in newCostlyShops.
After that, I removeChild() that object and splice it out from the array.
My Code:
Array 3:
var newCostlyShops:Array = new Array();
newCostlyShops = Object(root).WorkScreen_mc.returnCostlyShops();
trace(newCostlyShops); // this is tracing out the exact shopCodes I want and is working fine.
Deletion and Splicing codes:
for (looper = 0; looper < upgradeButtonsArray.length; looper++) {
for (var secondLooper: int = 0; secondLooper < newCostlyShops.length; secondLooper++) {
if (upgradeButtonsArray[looper].shopCode == newCostlyShops[secondLooper]) {
trace(looper);
trace(upgradeButtonsArray[looper]);
removeChild(upgradeButtonsArray[looper]);
upgradeButtonsArray.splice(looper, 1);
}
}
}
for (looper = 0; looper < buyButtonsArray.length; looper++) {
for (secondLooper = 0; secondLooper < newCostlyShops.length; secondLooper++) {
if (buyButtonsArray[looper].shopCode == newCostlyShops[secondLooper]) {
trace(looper);
trace(buyButtonsArray[looper]);
removeChild(buyButtonsArray[looper]);
buyButtonsArray.splice(looper, 1);
}
}
}
What's wrong with this Code:
I keep getting error
TypeError: Error #1010: A term is undefined and has no properties.
This error comes only after the 1st time this code is run and not the first time it is run. When I remove the removeChild and splice , this traces out objects that are not null, ever. Even after this whole function is called 100 times, the error is not shown. Only when I removeChild and use splice this occurs.
Is there something wrong with what I'm doing? How to avoid this error? This is throwing the whole program haywire. If there is any other alternative to this method, I'm open to take those methods as well as long as I don't get errors and my goal is reached.
It might sounds funny, but.... try to decrement looper after splicing.
trace(looper);
trace(upgradeButtonsArray[looper]);
removeChild(upgradeButtonsArray[looper]);
upgradeButtonsArray.splice(looper, 1);
looper--;
I think after splicing the array all item's are being shifted and you're skipping next one.
Also, you should get some more information with this error, like which class/line is throwing it. Maybe you need to enable "permit debugging" or something?
Bonus suggestion:
For newCostlyShops use Dictionary instead of Array so you won't have to nest for inside for...

AS3 adding EventListener to array of movieClips but getting error #2007 :Parameter listener must be non-null

I am trying to add an event listener to ALL of my buttons in the buttons array. I can make them buttons within the loop but when I try and add the event listener is give me this error:
TypeError: Error #2007: Parameter listener must be non-null.
at flash.events::EventDispatcher/addEventListener()
at Main()
I can add this event to another array but just not this one. Ive placed these buttons on the stage and gave them instance names which I'm referring to in my as file. I am learning AS3 in school so this is probably a very obvious problem but Im not qualified to debug my code yet :S Thanks for all your help.
//array of buttons and making them buttons
var buttons:Array = [armButton, lobeButton, beakButton, crotchButton, earButton, hairButton, legButton, shoulderButton, spineButton, tailButton, tearButton, eyeButton];
for(var b:int = 0; b<buttons.length; b++){
buttons[b].buttonMode = true;
buttons[b].addEventListener(MouseEvent.CLICK, clickMe);
}
function clickMe(e:MouseEvent):void{
trace("hello");
}
Check the name of the "clickMe" function both in definition and parameters-section, make sure that exactly the same characters are used (a character can sometimes be mistaken for the character from another code table). The error occurs because "clickMe" expression is null at the moment when the loop is being executed.
var buttons:Array = [armButton, lobeButton, beakButton, crotchButton, earButton, hairButton, legButton, shoulderButton, spineButton, tailButton, tearButton, eyeButton];
for(var b:int = 0; b<buttons.length; b++){
buttons[b].buttonMode = true;
// what is the output of the following expression?
trace(clickMe) // should be "function Function() {}"
buttons[b].addEventListener(MouseEvent.CLICK, clickMe);
}
function clickMe(e:MouseEvent):void{
trace("hello");
}
In your addEventListener line clickMe is null.
I suspect that we aren't seeing all the code here. Is that code together in the same file ? Or did you cut/paste just parts you thought were important ?

Resources