5

I have an hero array that I show it in list by *ngFor and when I Click on one of it element it copied on new variable and new variable go to input by tow way binding . my heroClass:

export class Hero {
    id: number;
    name: string;
  } 

my hero-mock list:

import { Hero } from './heroClass';

export const HEROES: Hero[] = [
  { id: 11, name: 'Mr. Nice' },
  { id: 12, name: 'Narco' },
  { id: 13, name: 'Bombasto' },
  { id: 14, name: 'Celeritas' },
  { id: 15, name: 'Magneta' },
  { id: 16, name: 'RubberMan' },
  { id: 17, name: 'Dynama' },
  { id: 18, name: 'Dr IQ' },
  { id: 19, name: 'Magma' },
  { id: 20, name: 'Tornado' }
];

My hero component:

   import { Component, OnInit } from '@angular/core';
    import { Hero } from '../hero';
    import { HEROES } from '../mock-heroes';

    @Component({
      selector: 'app-heroes',
      templateUrl: './heroes.component.html',
      styleUrls: ['./heroes.component.css']
    })
    export class HeroesComponent implements OnInit {

      heroes = HEROES;

      selectedHero: Hero;


      constructor() { }

      ngOnInit() {
      }

      onSelect(hero: Hero): void {
        this.selectedHero = hero;
      }
    }

heroes.component.html

<h2>My Heroes</h2>
<ul class="heroes">
  <li *ngFor="let hero of heroes"
    [class.selected]="hero === selectedHero"
    (click)="onSelect(hero)">
    <span class="badge">{{hero.id}}</span> {{hero.name}}
  </li>
</ul>

<div *ngIf="selectedHero">

  <h2>{{ selectedHero.name | uppercase }} Details</h2>
  <div><span>id: </span>{{selectedHero.id}}</div>
  <div>
    <label>name:
      <input [(ngModel)]="selectedHero.name" placeholder="name">
    </label>
  </div>

</div>

the problem is when i select one hero and show copy of it on text input and change it the hero of list that is selected changing too.

in angularjs 1 I prevent from this issue by using angular.copy() built in method but in angular 2 i have to create new of Hero and attributing propery of selectedHero to main hero:

  selectedHero: new Hero();
onSelect(hero: Hero): void {
        this.selectedHero.name = hero.name;
         this.selectedHero.id= hero.id;
      }

is there other way to deep copy in angular 2 without using jquery or js function and above way?

6
  • i don't want use js functions Commented Dec 17, 2017 at 7:23
  • 1
    The same way as in any other JS application. It isn't the responsibility of the framework to provide general helper functions. The fact AngularJS tried to emulate jQuery API and provided copy and extend shouldn't be taken into account and means that something went wrong there. Commented Dec 17, 2017 at 7:36
  • 1
    You are using a JavaScript framework and you do not want to use JavaScript functions? What? Commented Dec 17, 2017 at 7:39
  • This is angular - not angularJS @estus Commented Dec 17, 2017 at 7:53
  • 1
    @LazarLjubenović angularJS is a javascript framework - angular is typescript... Yes it compiles to javascript and I get that, however searching for a typescript specific answer is acceptable. Commented Dec 17, 2017 at 7:54

2 Answers 2

13

This is pretty hacky in my opinion, but it does work.

this.selectedHero = JSON.parse(JSON.stringify(hero));

For Shallow Copy: You can use the spread operator:

this.selectedHero = {...hero};
let {...example} = hero;
Sign up to request clarification or add additional context in comments.

1 Comment

The spread operator will do a shallow copy, which might not be what the developer wants. The JSON trick will mess with things like Dates and other complex objects, including circular references.
5

Use lodash's cloneDeep function.


There's nothing in Angular for deep cloning an object because it is not Angular's concern to provide such a function.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.