Teemu Turkia
Teemu Turkia

Reputation: 100

Why is Angular component modifying data in service?

I have an Angular service which holds list of data in BehaviorSubject. When a component is requesting the data from the service, it will be passed there as an observable. In my understanding the data should be immutable in the component, but whenever I make changes to the data in the component, it also changes in the service.

So the problem is if user edits the data in edit view and then clicks cancel, the data has been already altered in service. I created a sample app to demonstrate the problem: https://stackblitz.com/edit/angular-ivy-jicj96

How should I store and pass on the data in service so that component cannot modify it directly?

Upvotes: 0

Views: 370

Answers (2)

Quaz4
Quaz4

Reputation: 46

The banana box syntax [()] uses two way binding to update your model automatically when you make changes in the front end. This differs from one way binding, [] and {{}}, where changes are not reflected in the model.

You should read about Data Flow in Forms in the Angular docs to learn how to overcome this problem.

Upvotes: 1

Barremian
Barremian

Reputation: 31115

You're passing around references to objects. Objects in Javascript are finicky with passing data by reference. See here and here for more info on how objects are passed in Javascript.

You could try to subscribe in the controller and create a deep clone of the object using JSON.parse(JSON.stringify(object)).

edit-person.component.ts

export class EditPersonComponent  {
  person: Person;

  constructor(private router: Router, private personService: PersonService, route: ActivatedRoute) {
    const personId = +route.snapshot.paramMap.get('personId');
    personService.findById(personId).subscribe(
      person => { this.person = JSON.parse(JSON.stringify(person)) }
    );
  }
}

edit-person.component.html

<div *ngIf="person">
  Name: <input [(ngModel)]="person.name" name="name">
  <br>
  Age: <input [(ngModel)]="person.age" name="age" type="number">
  <br>
  <button (click)="save(person)">Save</button>
  <button (click)="cancel()">Cancel</button>
</div>

I've modified your Stackblitz

Upvotes: 2

Related Questions