While I was testing my code, I accidentally ran into unexpected mutation.... Or maybe... I am just doing it all wrong...
User
constructor(
public id: number,
public education: Education[]
){}
UserStateService
private user = new BehaviorSubject<User>(null);
setUser(user:User){
// set by HttpClient or perform an update
this.user.next(user);
}
getUserDetail(){
return this.user.value;
// this.user.getValue(); => tried this as well same thing...
}
updateUserDetail(user:User){
// Maybe perform some check method before the update
this.user.next(user);
// HttpClient to save on db
}
I have a form in my component that user will modify their own data. So my idea here is to call getUserDetail()
thinking that the return object should be readonly. Once I have set the new value I would then updateUserDetail()
to update the observable with next()
, but I experienced otherwise...
Component
onSubmit(){
let currentUser = this.userService.getUserDetail();
console.log("Original User => ", currentUser); // array(2) see screen shot highlighted
currentUser.educations = this.userForm.value['educations'];
console.log("Modify User => ", currentUser); // array(1)
// this.userService.updateUserDetail(currentUser);
}
currentUser.educations = this.userForm.value['educations'];
I don't want this to automatically update the observable, because there will be times where I might need to validate information before making the change.... how can I achieve this?
Thank you
I am not sure if this is the correct way... If you find this solution to be a bad practice please state the problem and also provide the solution. I am happy to change the marked answer.
But this is how I did it.
I basically have another variable to act sort of like a liaison to my subjects. This created numerous benefits such as validating data before .next() observable.
This is what the code looks like
private userSubject = new BehaviorSubject<User>(null);
user$ = this.userSubject.asObservable(); // -> prevent .next() be called on the component
private user: User = null;
setUser(user:User){
this.user = user
// if(user) -> so some check if you desire
this.userSubject.next({...this.user}); // use spread syntax to make a copy so it does not directly refere to this.user
}
// -> Don't need this any more. Just subscribe to user$
// getUserDetail(){
// return this.user.value;
// this.user.getValue(); => tried this as well same thing...
//}
The following solution was inspired by this article https://codeburst.io/javascript-es6-the-spread-syntax-f5c35525f754
Document link for spread syntax https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With