Delete object reference in javascript - javascript

I am pretty new in js and angularjs and ran into some basic problem i can't solve.
I add the $scope.consignations to the view with ng-repeat. Its a big object with several layers. In the sample code, i assign the $scope.consignations to the temp and after that, i "navigate" inside the temp object and at some point i push data to the temp. It changes the view, as expected.Now i want to clear the $scope[elementName] obj, but it clears the pushed data as well from the view. I've tried to delete the temp reference (i assume its only a reference of the $scope.consignations obj.) and i cant access it anymore, but when i clear the $scope[elementName] it clears the view anyway.
$scope.addElements = function(elementName){
temp=$scope.consignations;
for (var key in someArray) {
//here i "navigate" recursive inside temp
}
temp.push($scope[elementName]);
delete temp;
for (var key in $scope[elementName]) {
$scope[elementName][key]="";
}
};

temp=$scope.consignations by doing so your temp & $scope.consignations references same object.
So change in any object will be reflected in other object as well as in view.
So you should copy it like $scope.temp=angular.copy($scope.consignations) and then use $scope.temp for view binding and $scope.consignations for other purpose.

If you want to copy an existing element from $scope to a new $scope variable and delete the old one then you can use the following approch.
$scope.consignations.push(angular.copy($scope[elementName]));
delete $scope[elementName];
Assuming $scope.consignations is you new array where you want to store the data and $scope[elementName] is your old one which you want to delete.

In case you are using definedProperty, angular will not copy these.
This snippet will help you out then.

Related

How to reasign object with `this` in Angular component?

I have 2 variables inside an Angular component/class FilterComponent that point to an object. The first one (localStorage) stores the results of the current filtering choices that the user makes and is connected with toogle buttons with [(ngValue)]. The second one (globalStorage) gets the results of filtering choices that the user made earlier within other components (if you for example click on fruit on home page,globalStorage.food gets updated, but not the localStorage within FilterComponent). I have a method that should assign gloablStorage to localStorage when the user open the filter that looks like this:
openFilter() {
this.localStorage = this.globalStorage; //this line is responsible for strange behaviour
...
}
This works exactly like it should, but only after the apply button on filter (within FilterComponent) is clicked, which is responsible for sending the contents of localStorage to globalStorage (via next/behaviourSubject).
For some mysterious reason, before that happens, the values of toggleButtons get assign to globalStorage as well as to localStorage (although they are connected only to localStorage). Why is this happening and how can I fix it?
when you do this.localStorage = this.globalStorage; and these 2 variables are objects, it means this.localStorage now point/refer to this.globalStorage, so from now on this 2 variable will refer to 1 place.
If you just want to copy data inside it you should do a copy instead of simple assign by using either Object.assign(shallow copy) or this.local = {...this.global} for loop deep copy
Thank you all for your help. The solution (that's good enough for now) was to reassign each property:
this.localStorage.property1 = this.localStorage.property1;
this.localStorage.property2 = this.localStorage.property2;

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);
}

Correctly mapping array element using the Knockout mapping plugin

I have a viewModel that looks something like this when simplified:
var viewModel = function(){
var self = this;
self.selectedObject = ko.observable({});
self.getUnit = function(){
//get the selected object from the server side as json
self.selectedObject(ko.mapping.fromJS(data,mapping));
};
self.addObjectMember = function(){
self.selectedObject().objectMembers.push(new ObjectMemberViewModel(null, self.selectedObject()));
self.save = function(){
var data = ko.mapping.toJS(self.selectedObject);
//ship data to server
}
The data received from the server contains an array called objectMembers that has some properties inside it. The properties might differ between different objects.
My mapping object look like this:
var mapping = {
'objectMembers': {
create: function(options){
return new ObjectMemberViewModel(options.data, options.parent);
}
}
};
To see my problem, I'll give an example:
The user loads the page, and then fetches an object. That object includes two elements inside the objectMembers array. Then those are mapped using the ko.mapping.fromJS and everything works just fine. I can modify my viewModel using my model and the viewModel is updated. Then the user clicks a button that triggers the addObjectMember function, adding a third entry to the observableArray. I can interact with this also, and any changes done to my model can be seen in the viewModel as expected.
The problem comes when I click save. If I debug the save method, and check the contents of self.selectedObject, I can see that it contains what I want it to, but the object that is mapped back into the variable data has the last element in the objectsMembers array as an empty object ({}). The two other object look as I want them to.
I think I know why. The two first object have their __ko_mapping__.mappedProperties containing all the properties they had when it got mapped initially. The last one however has an empty __ko_mapping__.mappedProperties, and therefore I guess that no properties are mapped back.
So I need to do one of these things I guess:
When adding the object to the array on addObjectMember I need to get the __ko_mapping__.mappedProperties set so that it gets mapped back when I save.
When mapping back, I include all the properties on the mapped object regardless of their presence inside the __ko_mapping__.mappedProperties.
I have no clue how to do any of them that does not feel like a dirty hack, so any help here would be appreciated.
I ended up using ko.toJS instead of ko.mapping.toJS. ko.toJS does not care about __ko_mapping__, and maps everything (including __ko_mapping__).
That means it maps a bit more than I need, but other than that it works just fine.

Removing an entire key from a JavaScript Object

This may be a case of my lack of terminology, however if someone could enlighten me on this I'd appreciate it:
I have a routine which returns a JSON array, works perfectly however I then wish to do some calculations based on what's passed.
I've therefore copied the array into a temporary object (called tmp), and I then wish to remove certain 'keys' (?) from this object that aren't necessary.
For example, my 'tmp' object starts out as having:
fldCat2, fldCat3 and many more.
What I don't need is anything related to 'fldCat3', so I wish to remove that entire key from the object.
To test this I've done the following:
console.log(tmp);
delete tmp.fldCat3;
delete tmp['fldCat3'];
var prop = "fldCat3";
delete tmp[prop];
console.log(tmp);
Yet not one of those delete methods deletes 'fldCat3' from the tmp object.
Is there something pretty damn obvious I'm missing?
edit
have attached a screenshot of the object from within Firebug (values removed)
Given your screenshot I am assuming that your problem is that you are trying to remove properties from what is actually an array of objects with these properties.
You will have to do something like this
for (var i = 0; i < tmp.length; i++)
delete tmp[i].fldCat3;
Here you loop through all the elements of said array removing fldCat3 from each of these.
I have experienced that problem too. What I have done is using UnderscoreJS's _.compact(myObject) after deleting the key from the object.

How can I copy element by 'pass by value' not by 'pass by reference'

Below is the snippet of the code. Basically, 'this.leaves' is a array. And I want to shift first array element, make copy of it (called frontLeaf), and unshift it to the original array, change some attributes from copied element, and put that element to the parent array element.
var frontLeaf = this.leaves.shift();
this.leaves.unshift(frontLeaf);
frontLeaf.leftChild = tmp;
frontLeaf.rightChild = this;
this.parent.leaves.push(frontLeaf);
My problem is that frontLeaf seems to be passed by reference that when I assign
frontLeaf.leftChild = tmp;
frontLeaf.rightChild = this;
above two lines of code seems to affect both elements in this.leaves and this.parent.leaves... So, How can I resolve this problem?
Javascript passes all objects by reference. The only way to do what you're looking for is to create an entirely new object, do a deep copy and then push it.
See this post for a sample solution using jQuery.
Yes, in JavaScript objects are always passed by reference. If you want a copy of an object, you'll have to write a deep-copy routine yourself.
I'm not sure exactly what you're trying to do (what is tmp? what is this? what is this.leaves an array of?), but maybe there is a way to do it without needing a copy?
Here's what I did when faced the same issue:
var newObj = JSON.parse(JSON.stringify(oldObj));

Categories