I have a component which is displaying some data on a page from a subscription.
I am trying to clone
that variable and make changes to it without impacting the original data being used to render the view of the page.
import { UtilsService } from '../shared';
import { Component, Input, OnInit } from '@angular/core';
@Component({
selector: 'app-review',
templateUrl: './review.component.html',
styleUrls: ['./review.component.css']
})
export class ReviewComponent implements OnInit {
@Input() payload: any = null;
// Object of strings that are used for the details
langStr: any = {
noDepartment: 'No Department Change',
noSegment: 'No Segment Change',
noMarket: 'No Budget Market Change',
noIncentive: 'No Incentive Plan Change',
noRole: 'No Role Change',
noProductionDate: 'No Production Date Change',
noLanguage: 'No Language Change',
noShift: 'No Shift Change',
noSupervisor: 'No Supervisor Change'
};
// Used to scan through the final payload and assign default values if missing
optionalFields = ['budgetMarket',
'hierarchy',
'incentivePlan',
'primaryLanguage',
'secondaryLanguage',
'role',
'segment',
'shiftID',
'supervisor'];
modifiedData: any;
constructor(
private utils: UtilsService
) {
}
ngOnInit() { }
submitChanges() {
this.modifiedData = this.payload;
// Loop over all of the keys in our formData object
for (const key in this.modifiedData.formData) {
// Find shift by property if the key exists within our defined array
if (this.modifiedData.formData.hasOwnProperty(key) && this.utils.isInArray(this.optionalFields, key)) {
// If our object data doesnt have a value, set it to -1
if (!this.modifiedData.formData[key].length) {
this.modifiedData.formData[key] = '-1';
}
}
}
// Send to database
console.log(this.modifiedData)
}
}
In this situation above, I am trying to set my subscribed data of this.payload
to a new variable called modifiedData
. I am then modifying some of the data in that assignment.
However, as soon as I call the function submitChanges()
, my HTML view gets updates with the changes made to modifiedData
, even though its not subscribed to that.
I assume it is something to do with this.modifiedData = this.payload;
somehow updating the original data (payload
).
Is there a way to do this where payload
wouldn't be touched. I am essentially just cloning that and making a few changes before submitting it to my database call.
Use something like this:
// Clone the object to retain a copy
this.originalProduct = Object.assign({}, value);
Or in your case:
this.modifiedData = Object.assign({}, this.payload);
This copies the values of all properties from this.payload
into a new object.
The documentation for this is here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign AND includes a discussion of the "deep cloning" issues.
Otherwise, this code:
this.modifiedData = this.payload;
is assigning a reference. So any change to the original changes the "copy" as well.
You're not cloning the object. You are just assigning the reference to that object to another variable. They both point at the exact same object.
If you want to actually clone your object you have basically two options:
First, easy, a little bit hacky and to be used carefully since not everything will be covered:
this.modifiedData = JSON.parse(JSON.stringify(this.payload));
will give you a new object basically cloned.
If you want to have a more robust cloning, you have to do it manually by traversing through your object and creating a new one from scratch (or use a library like lodash, which has methods for this).
Update just for completion: The other answers suggested this.modifiedData Object.assign({}, this.payload)
and this.modifiedData = {...this.payload};
which is fine for simple, not nested objects because both do a shallow copy
not a deep copy
of your object.
Since JSON.parse(JSON.stringify(obj)
will ignore everything else than Objects, Arrays, Numbers and Strings and Booleans, the probably best option to take is still a manual clone (or using a library which does it like lodash).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With