Home > front end >  When selectedHero gets edited it affects the List of Heroes
When selectedHero gets edited it affects the List of Heroes

Time:06-28

Here is the interface of Hero

export interface Hero {
id: number,
name: string
}

List of Hero

import { Hero } from './model-interfaces/hero';

export const HEROS: Hero[] = [  
{ id: 12, name: 'Dr. Nice' }, 
{ 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' }
];

Component of the Hero

export class HerosComponent implements OnInit {  

  heros = HEROS;
  selectedHero?: Test;    

  constructor() { }

  ngOnInit(): void {
  }

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

HTML of the Hero list

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

<app-hero-details [hero] = "selectedHero"></app-hero-details>

To get the selected Hero

export class HeroDetailsComponent implements OnInit {

  @Input() hero?: Hero

  constructor() { }

  ngOnInit(): void {
  }

}

HTML for the selected Hero

<div *ngIf="hero">
<h2>{{hero.name | uppercase}} Details</h2>
<div>ID: {{hero.id}}</div>
<div>
  <label for="hero-name">Hero name: </label>
  <input id="hero-name" [(ngModel)]="hero.name" placeholder="name">
</div>

Here when I select a hero from the list of hero. The selected hero gets displayed at the bottom of the page in a text box. When I make changes to the selected hero in that text box I don't why the selected hero in the list gets changed.

Because the selected hero gets stored in a separate variable. How does the selected Hero in the Hero List gets changed?

CodePudding user response:

Because the selected hero gets stored in a separate variable

Since heroes are objects, the separate variable is in fact only another reference to the same object in memory. Consider a trivial example:

const obj1 = { name: "Object 1" }
const obj2 = obj1; // the same object, not copy
obj2.name = "Object 2"; // affecting the object referred by obj2, which _is_ the object referred by obj1

console.log(obj1.name);

"Separate variable" would behave like you expect to if it was a primitive (e.g. string, number, boolean).

CodePudding user response:

Thats because you pass a link to your selected hero object in HeroDetailsComponent.

The [(ngModel)]="hero.name" statement can be rewrited like [ngModel]="hero.name" and (ngModelChange)="hero.name = $event"

When you edit your hero name in input ngModelChange emits new value and mutate hero object in your heroes list.

If you want to watch how your hero list change you can rewrite it this way:

export class HeroDetailsComponent implements OnInit {

  @Input() hero?: Hero

  constructor() { }

  ngOnInit(): void {
  }

  onHeroNameChange(name: string): void {
     this.hero.name = name;
  }
}

and your html will be:

<div *ngIf="hero">
<h2>{{hero.name | uppercase}} Details</h2>
<div>ID: {{hero.id}}</div>
<div>
  <label for="hero-name">Hero name: </label>
  <input id="hero-name" [value]="hero.name" (input)="onHeroNameChange($event.target.value)" placeholder="name">
</div>
  • Related