I'm working on an angular2 app that takes advantage of several services to share date throughout the app.
In one part of my app, I have an edit function that allows the user to modify the data in an array.
In this case, when the user modifies a property in the component, the corresponding data in the service is also modified without setting it directly.
I'm about 6 months in to learning angular, but I know that setting one array equal to another is actually pointing at the same object. So in this case, I have a method in the service that returns the array as a slice(), which is I believe is supposed to create new array to avoid the user being able to modify the service data directly.
The full app that I'm working on is fairly complex, but I was able to create a bare bones angular app to demonstrate what is happening.
test.component.html:
<div *ngFor="let item of testComponentData">
<p>{{ item.fname }} {{ item.lname }} <button (click)="onUpdate(item.id)">Update</button></p>
</div>
test.model.ts:
export class TestObject {
constructor(public id: string, public fname: string, public lname: string) {}
test.service.ts:
@Injectable()
export class TestService {
constructor() { }
private serviceData: TestObject[] = [
new TestObject('1', 'Joe', 'Smith'),
new TestObject('2', 'Mary', 'Jones'),
new TestObject('3', 'Larry', 'Murray'),
];
getData() {
return this.serviceData.slice();
}
}
test.component.ts:
export class TestComponent implements OnInit {
testComponentData: TestObject[];
constructor(private testService: TestService) { }
ngOnInit() {
this.testComponentData = this.testService.getData();
}
onUpdate(id) {
// Clicked 3rd button, id = 3
const temp = this.testComponentData.find(o => o.id === id);
console.log(this.testService.getData());
// 0: TestObject {id: "1", fname: "Joe", lname: "Smith"}
// 1: TestObject {id: "2", fname: "Mary", lname: "Jones"}
// 2: TestObject {id: "3", fname: "Larry", lname: "Murray"
setTimeout(() => {
temp.fname = 'Bartholomew';
console.log(this.testService.getData());
}, 5000);
// 0: TestObject {id: "1", fname: "Joe", lname: "Smith"}
// 1: TestObject {id: "2", fname: "Mary", lname: "Jones"}
// 2: TestObject {id: "3", fname: "Bartholomew", lname: "Murray"}
}
}
In the component, the testComponentData property is initialized in ngOnInit by calling the testService.getData() method, which returns this.serviceData.slice()
In this example, I am clicking the 3rd button to set the fname to 'Bartholomew.' As you see in the embedded comments, the testService data changes, even though I am only changing the component object (testComponentData), the service data is also being changed (this.testService.getData())
Timeout is just in there because sometimes the first console.log is laggy and log will show the value has changed already.
I can't for the life of me see how this is happening. I know there is something fundamental here, and I assume I am accessing the same object somehow, but I don't understand why.
Any help is appreciated. Thank you!