unbinding scope property in angular - javascript

Is there a way to unbind the reference when we are assigning values from scope properties?
For example I have $scope.X and $scope.Y. At some point in my function I want to assign the value of $scope.Y at that time to $scope.X:
$scope.X = $scope.Y
However, whenever scope.Y changes, looks like $scope.X changes too. Is there a way to avoid the chain? I just want to assign the value of $scope.Y once.
I tried using angular copy but it didn't work:
$scope.X = angular.copy([$scope.Y])[0];
Thanks

angular.copy should produce a clone of the object. There are a few other methods that may be perform better, see What is the most efficient way to deep clone an object in JavaScript? . I already use lodash for other stuff in my site so I use the _.cloneDeep method.

Related

Javascript changes value of three objects at once

This is my code and I am trying to change value of object in packs object. But when I type it, Javascript somehow changes all three different objects, that have nothing in common. And this is the only line that changes packs, rest should stay the same, but it's all changing with this line. How?
console.log(packs[usedPack].levels[level].bestBy) //null
console.log(defaultPack.levels[level].bestBy) //null
console.log(mainPacks[usedPack].levels[level].bestBy) //null
packs[usedPack].levels[level].bestBy = nameTyped; //this changes values in three different objects
//packs[usedPack].levels[level] = nameTyped; //if I type like this, this does change only original object, rest stays the same
console.log(packs) //nameTyped
console.log(defaultPack) //nameTyped
console.log(mainPacks) //nameTyped
Edit: It was indeed problem with referencing. I was using constructor function and this function needed to deep copy complex objects. I was checking values and I used multiple loops to copy all values from objects, but it didn't work properly. I've changed all of this to JSON.parse(JSON.stringify()), and it's working now. Thanks for help.
The issue here seems like you're assigning some object by its reference.
In javascript, if you have two objects and you assign them like
a = b;
Now whenever you will change b, a will also be changed. To avoid this we do deep clone using the spread operator
// this now does not reference to b but clones it
a = {...b}
In your code, you might be assigning some objects like this. a=b
Maybe you're assigning packs, defaultPack, and mainPacks using some same object.
Updated
#David pointed out one thing and that is if you are having some complex structure (like objects within object) and then you clone it using spread operator, the inner objects will still reference the same object.
To resolve this, for easiness you can use lodash deepclone function
const clonedeep = require('lodash/clonedeep');
const deepClonedObject = clonedeep(originalObject);
This will deep clone and even if the objects are nested they won't refer to the same object.

How to duplicate object in JS where duplicate changes if you change original

I am making a planner/calendar website that is going to have a repeat function.
var chain = _.chain(state.items).filter({'id': 1}).head().value();
console.log(chain);
Here i filter one object, how do i duplicate chain that when i change the original the duplicate also changes and the other way around?
Variables that are assigned a non-primitive value are given a reference to that value. That reference points to the object’s location in memory. The variables don’t actually contain the value. This is why the original value changing when you're changing the duplicate.
This can be solved by using JSON.parse() and JSON.stringify()
Create a new function in the methods section
cloneObject:function(obj){
return JSON.parse(JSON.stringify(obj));
}
Now you can call this method to make a copy of any object, like
var items = this.cloneObject(state.items); // this will create a clone of the object
var chain = _.chain(items).filter({'id': 1}).head().value();
Here the filter won't effect the state.items since we made a clone of this data.
If you're already using lodash JS library, you can use the cloneDeep() method to make the copy
Eg:
var items = _.cloneDeep(state.items);
var chain = _.chain(items).filter({'id': 1}).head().value();
console.log(chain);

Having trouble with assigning scope to variable to manipulate

Attempting to assign a scope object to a JavaScript variable to do minor manipulation before sending to my API. However, any changes made to the JavaScript variable change the scope object.
var recruitingCallListOutput = $scope.RecrutingCallingList.Recruit;
// manipulation of recruitingCallListOutput
The manipulation actually still updates the scope object which is not desired. Feel I am not understanding something in AngularJS correctly. Is there a way to grab the data and detach it from the scope?
In your example, recruitingCallListOutput is a reference to $scope.RecrutingCallingList.Recruit (see https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0 for more detail.) You will want to make a copy of $scope.RecrutingCallingList.Recruit.
If Recruit is a shallow object, meaning no nested objects (property values are primitives only), you can simply do
var recruitingCallListOutput = Object.assign({}, $scope.RecrutingCallingList.Recruit);
If you have nested objects/arrays as property values, you'll need to deep copy. It's been a while since I have been in the angular world, but
var recruitingCallListOutput = angular.copy($scope.RecrutingCallingList.Recruit)
you could actually use angular.copy in both examples.
This is nothing to do with AngularJS. It's Javascript, and it's expected behaviour.
For example, if you open the browser console (F12->Console) right now and run this:
var foo = {x:1};
var copy=foo;
copy.x=2;
console.log(foo.x);
you will see {x:2} printed out.
This is the same behaviour you would expected for any object reference in Javascript, C#, Java, etc. Because you are making a reference and not a copy, any changes to the reference are actually changes to the original.
The simplest way to solve this problem in your case is to copy the values you are interested in from the item in question into a totally separate object and modify that copy.
e.g.
var recruitingCallListOutput = {
name: $scope.RecrutingCallingList.Recruit.name,
age:$scope.RecrutingCallingList.Recruit.age,
modifiedSomething: $scope.RecrutingCallingList.Recruit.something + 42 //or whatever modifications you need to make
...and so on.
};
There are ways to "clone" an object in Javascript but unless your object is really really complex I would be careful. And consider if you really need all of the properties of the original object anyway, perhaps you only need to send some of them to your backend.

AngularJS create new scope from scope

I don't really understand why this piece of code works the way it does.
I call my service and get the expected data returned. I wish to store the pictures seperately, as I need to modify the array and parse it differently to new scopes. The thing I don't understand is, that as I now have created 2 scopes, product and productPictures - why are these still linked?
If I use Lodash to _.sort() productPictures, then the Images object inside scope.Product will also be altered, however I do not want this happen, and I don't know how to isolate the $scope.productPictures. I tried handling the scopes as simple js variables such as var product; and var productPictures, but as I set their data according to the response from the service, they are still linked.
$api.productpage.query({
id: parseInt($stateParams.productId)
}, function (data) {
$scope.product = data[0];
$scope.productPictures = data[0]['Images'];
});
Am I overlooking something super trivial? Should I rather manage the product images in a seperate service request?
Objects are passed by reference in javascript. It means that in this code
$scope.product = data[0];
$scope.productPictures = data[0]['Images'];
$scope.productPictures points to the same object (I guess this is array in your case) as data[0].Images.
To overcome this issue you need to clone object instead of just reference. You might want to check angular.copy method:
$scope.productPictures = angular.copy(data[0].Images);
You create two variables in the scope not two scope.
Object are passed by reference so if you modify one it modidy the other.
Maybe try to clone the object
edit use angular.copy() instead of jquery.extend()
function myclone ( obj){
return jQuery.extend(true, {}, obj);
}

strange angularJs variable behavior

Kindly explain me this behavior. I have decalred 2 variables.
$scope.data = {'value' : 123};
$scope.v1 = $scope.data;
Now if i change the value
$scope.data.value = 2;
and try to print
alert('old value is '+$scope.v1.value);
It gives me output as 2 whereas I think it should give me value as 123.
Kindly tell me that is it the same behavior like Java where one variable has different instances and change in one reflects in another ?
As you're guessing you are not creating a new object when you assign $scope.data to $scope.v1. You're just "pointing" $scope.v1 to $scope.data which implies that any change that you do to $scope.data will be reflected also in $scope.v1.
If you want to have different elements you should make a copy of the object. Look at angular.copy
Yes. You want to use angular.copy() to solve your current issue.
Anyways this all happens because of making one Object equal to another is assigning a reference; not creating a copy.

Categories