44

I am working with Angular 2 with TypeScript. I have User Management component where I have table of whole users.

When any user in table is clicked then forms appeaer with his whole properties to edit. Choosing user occurs event as below:

 onUserSelected(event) {
        var selectedId = event.data.id;
        this.selectedUser = this.users.filter(user => user.id === selectedId)[0]
    }

The problem is when selectedUser is being edited his properties also changes in table and it doesnt look so good. I tried to create copy myself as below but it didn't help - user class

 clone() {
        var cloned = new User(this.id, this.login, this.name, this.surname, this.phone);
        return cloned;
    }

Maybe I am doing something which is not good practice in Angular2?

Wernsey
  • 5,411
  • 22
  • 38
miechooy
  • 3,178
  • 12
  • 34
  • 59

3 Answers3

77

Try using

this.user = Object.assign({}, currentObject);

As mentioned by @AngularFrance, this will only work for shallow-copying objects, seek another implementation if there's a need to deep-copy an object.

Amit
  • 4,274
  • 21
  • 25
  • 3
    Side note: `Object.assign()` is for shallow copies (NOT deep copies), which in the case of this question should work. – AngularChef Jan 28 '17 at 15:56
  • You're right, edited. – Amit Jan 28 '17 at 15:58
  • 26
    For deep copies, there's always the controversial `obj = JSON.parse(JSON.stringify(o));` – AngularChef Jan 28 '17 at 16:06
  • 10
    Spread is syntactic sugar: `this.user = { ...currentObject }` – debiasej Sep 05 '17 at 06:06
  • 1
    @AngularChef does JSON.stringify work well with dates? I had issues in the recent past. – Ananda Nov 20 '17 at 12:35
  • No idea. I haven't used it with dates. – AngularChef Nov 20 '17 at 13:44
  • JSON.stringify shouldn't work with any objects which need to be created using a constructor. It will only create simple objects (with the default object prototype etc) – Amit Nov 20 '17 at 13:50
  • JSON.stringify might be functional, but the performance hit of concatenating and parsing a string would be pretty bad if you need to scale up. It would be better to write a deep copy function that was aware of your structure instead of using something that iterates on the structure agnostically, trying to figure out the bounds of your structure in addition to an already expensive copy. Creating clone functions for each object that needs to be cloned is reasonable, but works better with classes. – Kirk Mar 13 '21 at 15:21
18

You can use lodash :

https://lodash.com/docs#cloneDeep

lodash is recommended for lot of objects / array manipulations

almog
  • 798
  • 1
  • 7
  • 18
7

You could bind your editor form to an empty User object, say editUser, instead of the selectedUser variable (which points to an element of your user collection). In your onUserSelected(event), you'd initialize editUser via cloning the mutable properties of the selected user objects. Upon submitting the edit form ((ngSubmit)="editSubmit()"), you replace the original properties in the selected user object in the user collection.

Something along the lines of:

editUser: User = new User();
selectedId: number;
selectedUser: User;

onUserSelected(event) {
    this.selectedId = event.data.id;
    this.selectedUser = this.users.filter(user => user.id === this.selectedId)[0];
    this.editUser = this.simpleClone(this.selectedUser);
}

editSubmit(event) {
    this.selectedUser = this.simpleClone(this.editUser);
}

simpleClone(obj: any) {
    return Object.assign({}, obj);
}

The simpleClone implementation is not suitable for deep cloning, so if your User objects hold references to other objects, this should be turned into a proper cloning function.

András Szepesházi
  • 6,483
  • 5
  • 45
  • 59