scope variable updated automatically when I am updating another scope variable - javascript

I am getting ajax request data and assigning to one scope variable
$scope.customerEvents = data;
then I am using another variable to modify the data
var datanew=data;
datanew.unshift({'customer_events_id': 'ID','date':'Date','event':'Event','eventsubtype':'Event Subtype','eventtype':'Event Type','time':'Time','user_id':'User ID','user_mrn':'User MRN','user_name':'User Name','user_role':'User Role'});
$scope.downloadcsv=datanew;
But customerEvents is getting updated.

you should use:
$scope.customerEvents = angular.copy(data);
Creates a deep copy of source, which should be an object or an array.
That's the documentation.
Also you can look at this question: Javascript equivalent of assign by reference?

Sure, customerEvents and datanew are probably both referencing the same object (referenced by 'data'). Clone the array when you copy it to datanew and you'll be modifying only datanew and eventually $scope.downloadcsv and not customerEvents.
change var datanew=data; to var datanew=data.slice();

you have to do a deep copy of your object unless it will be referenced by the first variable.
you can use:
angular.copy(data)
angular.merge(dst, src) : documentation.
or you can use jquery.clone()
Also you can refer to this post : Deep copying objects in angular?

Related

Object gets copied, but i want the original

I have some global vars, which I know, bad code and all.
One of these vars: MyApp.player.pet, is an object of type pet, attached to the player object. It has some properties like "xp" which is just a number.
I am passing this object to a dynamic UI class that displays information about all kinds of objects, which is why I can't use the reference to the global var inside the object. Here is how I pass it:
var listOfProperties =
[MyApp.player.pet.name,
{"xp: ": MyApp.player.pet.xp},
{"xpToNextLevel: " : MyApp.player.pet.xpToNextLevel}];
then I transfer this list of properties to a new UI object as such:
new tooltipText(listOfProperties, ..., ...)
However, when the value gets updated inside MyApp.player.pet.xp the value inside the object tooltipText doesn't change. Somehow it's passing a copy, but I want to pass a reference if those are correct terms.
I've tried searching for this but all I can find are people asking how to make copies of objects, which seems to be what I've done unintentionally but not what I want.
How can I make sure that when MyApp.player.pet.xp changes, the value inside the tooltiptext also changes?
There is some misconception in your question:
You did not create copies of your original objects.
You merely copied some of their property values, by putting them into new objects (e.g. {"xp: ": MyApp.player.pet.xp}).
If you want to change the properties of your original objects, you need to change them there, not in your newly created small objects.
So if you want a generic list of properties, you need to keep a reference to your original object (MyApp.player.pet) as well. Example:
var listOfProperties = {
obj: MyApp.player.pet,
propertyNames: ['xp', 'xpToNextLevel']
}
You can then use the property names to generically set the properties of your original object:
var propertyName = listOfProperties.propertyNames[0];
listOfProperties.obj[propertyName] = newValue;

Why is my array being altered after using slice()?

I'm loading in a variable from my app-config.js file and then copying it with .slice() in an attempt to prevent its state from being mutated. Much to my chagrin, the function I'm using to alter data seems to be failing to respect this attempt at avoiding mutation. mySensitivityVarskeeps changing, although I'm not quite sure how since I'm only directly acting on mySeries. Any ideas as to why this is happening? Here's the code:
var mySeries = mySensitivityVars.slice();
//Dummy Processing Algorithm
function myDummyAlgo(sliderIndex, newValue, range) {
console.log(mySeries[sliderIndex].data)
var modifier = newValue/(range/2)
var newSeries = mySensitivityVars[sliderIndex].data.map(function(num){
return num * modifier
})
console.log(newSeries)
// mySeries[sliderIndex].data = newSeries
// console.log(sensitivityChart.series[0].data)
sensitivityChart.series[sliderIndex].setData(newSeries);
};
Slice can copy the array but any objects that are referenced inside the array are not getting copied (only a reference is copied)
Without seeing the contents of mySensitivityVars it's hard to tell, but my guess is you're mutating a reference to the original object rather than a duplicate object.
Do you have any objects in mySensitivityVars? If so, the corresponding objects in mySeries will be pointing to the original objects in mySensitivityVars rather than standalone duplicates, which is why you're probably seeing the mutation issues.
You should clone the array instead of copying it if you'd like it to be mutated. you can use JSON.parse(JSON.stringify(mySensitivityVars)) which is pretty fast deep cloning technic.
that would ensure new objects are assigned and not copy of the references.
When you do:
mySeries[sliderIndex].data newSeries;
The array mySeries is a copy of mySensitivityVars, but the objects in the array are not copies. Both arrays contain references to the same objects, and modifying the data property affects them both. You need to copy the objects as well:
mySeries = mySentitivyVars.map(o => Object.assign({}, o));
And if the objects contain references to other objects, you may need to do a deep copy. See What is the most efficient way to deep clone an object in JavaScript?

Angular - save scope value to variable, but not update it when scope updates

I have something like this:
$scope.last_good_configuration = $scope.storage;
In $scope.last_good_configuration I keep last good settings.
And when user type in input bad value, for example too big integer i want to do:
$scope.storage = $scope.last_good_configuration;
But my $scope.last_good_configuration is all the time the same as $scope.storage. How to stop updating $scope.last_good_configuration? I have to evaluate my scope somehow?
You need to make a copy or clone of the original object. Angular has a built in method for this: angular.copy.
$scope.last_good_configuration = angular.copy($scope.storage);
//Edits must be at least 6 characters workaround
You can create a new object using angular.copy() so when you make changes to storage it won't affect last_good_configuration
$scope.last_good_configuration = angular.copy($scope.storage);
Since objects are passed by reference, you need to create a new object to store default configuration in. Otherwise, when you modify $scope.last_good_configuration it also affects $scope.storage since they both point to the same object.
Use angular.extend method which will copy all properties from $scope.storage into the new object {}:
$scope.last_good_configuration = angular.extend({}, $scope.storage);
UPD. I totally forgot about dedicated angular.copy which is probably more appropriate in this case, especially is $scope.storage has nested object structure: angualar.extend will make a shallow copy, in this case you should use angular.copy (see Satpal answer).

underscore/lowdash passing reference to objectwhich I can't overwrite

I'm using the _.find() methid of Lodash to find an object and I am then trying to overwrite that object, like this...
taskToUpdate = _.find($scope.tasks, {ID: myID});
taskToUpdate = {};
This finds the reference to the task perfectly, but does not set it to an empty object, it has no effect.
However, if i pick a particular property and overwrite it, it works...
taskToUpdate = _.find($scope.tasks, {ID: myID});
taskToUpdate.title = "New title";
That works fine. I have a feeling the problem here is not lodash, but my bad understanding of how objects and references are passed between functions in javascript.
That's because you're setting the local variable taskToUpdate to an empty object, meanwhile $scope.tasks still retains the original reference to the unaltered object.
Once you have the reference to the object you can then get the indexOf.
var index = _.indexOf($scope.tasks, taskToUpdate);
And then can blank out the object reference in the $scope.tasks
$scope.tasks[index] = {};
At this point the reference in $scope.tasks will be a blank plain object, but tasksToUpdate will continue to hold the object reference. You can choose to continue to use it at this point, or not. But once you've ended all closures that have a reference to that taskToUpdate object, it will cease to exist.
My guess is that you actually want to remove the reference from $scope.tasks rather than just blanking out the object reference. You can do this many ways, but here is one:
$scope.tasks = _.without($scope.tasks, taskToUpdate);

Javascript is changing variable that needs only to be referenced

I'm pulling some data from a reference object changing it around for what I need, but for some reason my code is also changing the object i'm referencing..
var obj = {name:"list of things", list:[{name:"thing", 1},{name:"other thing", 2}]};
function doStuff () {
var ref = obj;
for(var p=0;p<ref.list.length;p++){
ref.list.splice(1,1);
}
return ref;
}
For some reason where I'm using this structure in my code, its changing 'obj' as well as 'ref'. can't seem to figure it out
The obj in your example is not an object, it is a reference to an object that lives somewhere in memory. This is why when you do ref=obj, you get another reference to the same object, so changing the object ref references is the same as changing the object obj references.
What you want to do is clone your object, so you end up with two different objects. There are some good answers regarding cloning on StackOverflow and the whole web for that matter. Feel free to use any of those.
JavaScript assignes by reference. You would need to do a deep copy in order to clone an object.
See: http://webdevwonders.com/deep-copy-javascript-objects/

Categories

Resources