Reputation: 55
I have a service with a property in it that I want to refer to and change in multiple components. Can I just reference it directly in my components by assigning it to a property in the component or should I subscribe to an observable? I tried it both ways and when I modify it in the component both ways seem to change the property in the service.
account.service.ts
export class AccountService {
constructor(private http: HttpClient) { }
testAccount: Account = {
domain_name: "fortestaccoutnpage2",
account_number: "fortestaccoutnpage2",
bill_timing: "anniversary",
}
getAccount(): Observable<Account> {
return of(this.testAccount);
}
}
account.component.ts
export class AccountComponent implements OnInit {
constructor(private _accountService: AccountService) { }
changeAccountNumber() {
this.account.account_number = "changed"
}
account: Account = this._accountService.testAccount;
grabAccount(): void {
this._accountService.getAccount()
.subscribe(account => this.account = account);
}
ngOnInit() {
//this.grabAccount();
}
}
Is the above example I basically have account
in the component refer to the testAccount
in the service and the changeAccountNumber
method works. I commented out the method to have account
subscribe to the observable, but when I do it that way it works as well. Is one way better than the other or are both fine?
Upvotes: 1
Views: 52
Reputation: 112
Use behavior Subject implementation from Rxjs, declare un your service and instace a behavior subject, after create another variable asObserver, them you must use the next method on behaviors subject implementations using in your component of interest for send last changes to your Behavior Subject in your service and later you can subscribe in any component U wanted the info
check this firts https://medium.com/@luukgruijs/understanding-rxjs-behaviorsubject-replaysubject-and-asyncsubject-8cc061f1cfc0
and this http://reactivex.io/rxjs/manual/overview.html
try something and after i can help U better
Upvotes: 0
Reputation: 1997
It's probably better to subscribe, instead of reference directly from the service.
The advantage of subscribe is that call will only be fired when the observable is called. So in this case it doesn't really matter, because you are just using a test object. But if you were calling from a server, you couldn't be sure when your data comes back. So if you clicked the button before the data came back, things could go south.
Additionally, currently you aren't doing anything except for assigning the account to a property. Which is valid. But if later you want to do something else, like have a loading spinner, and turn it off when you get the data. You would need to take advantage of the observable for sure.
Edit: Also, its probably not great practice to alter the account inside the component itself. That would work for sure, but it can lead to some confusing bugs and make things harder to test if you go that route. Its better for changes to be centralized. I would recommend adding a method to the service for changeAccountNumber(newNumber), and that service would push out a new observable with the changed account value. Kind of fancy, but its a lot more testable and I would argue more maintainable.
Upvotes: 3
Reputation: 1106
grabAccount(): void {
this._accountService.getAccount()
.subscribe(account => this.account = account);
}
here you are assigning value of account
(which is _accountService.testAccount
) to this.account
.
So this.account
and _accountService.testAccount
are references to the same object in memory. Changing one is always going to affect the other.
To avoid this you can simply clone the object before assigning it to this.account
Here is a simple way to do this:
grabAccount(): void {
this._accountService.getAccount()
.subscribe(account => this.account = JSON.parse(JSON.stringify(account)));
}
Or to avoid code duplication, you can clone in the service
getAccount(): Observable<Account> {
return of(JSON.parse(JSON.stringify(this.testAccount)));
}
This cloning method won't work if you have more complex objects (with Date values for example)
How do I correctly clone a JavaScript object?
Upvotes: 0