英文:
Unexpected page refresh when calling methods and managing state with Observable
问题
I've translated the code part for you:
// User informations and password handling variables
profileForm!: FormGroup;
public userProfile$?: Observable<any>;
passwordUpdateSuccess = false;
profileUpdateSuccess = false;
public groupDetails?: any;
// Wish handling variables and functions
wishes: any[] = [];
public showUpdateForm: boolean = false;
updateWishForm!: FormGroup;
showUpdateFormFor: string | null = null;
// Handling wish filtering
public originalWishes: any[] = [];
public filterForm!: FormGroup;
ngOnInit(): void {
// Handling wishes
this.wishListService.secretSantaService.wishesSubject.subscribe(wishes => {
this.wishes = wishes;
});
this.updateWishForm = this.formBuilder.group({
title: [' ', Validators.required],
url: [' ', Validators.required],
description: [' ', Validators.required],
price: [' ', Validators.required],
});
// Fetch the user profile and update the relevant fields
this.userProfile$ = this.userService.getUserProfile();
// Update form and wishes when userProfile$ emits a new value
this.userProfile$.pipe(
tap(userProfile => {
this.profileForm.patchValue(userProfile);
this.wishes = userProfile.wishList;
this.originalWishes = userProfile.wishList;
})
).subscribe();
// Initialize the filter form control
this.filterForm = this.formBuilder.group({
minPrice: [' '],
maxPrice: [' ']
});
// Adding a time between each key put in the filter form to avoid too many requests
this.filterForm.valueChanges
.pipe(debounceTime(500))
.subscribe((filterValues) => this.filterWishes(filterValues));
}
// ... (rest of your code)
I've removed some HTML tags and formatting for clarity in this response. If you have any specific questions or need further assistance, please let me know.
英文:
I'm developing an Angular application where I manage a User Profile page. This page displays user information and the user's wishlist, among other things.
The user can add, delete, or update wishes. Whenever these operations are performed, they are followed by fetching the updated user profile from the server using an Observable (userProfile$), which is supposed to update the UI.
But the problem is that everytime i'm passing a update, delete method, the full page is reloading and i can't find why.
Do anyone have an idea of why it's not working well ?
The get user profile method is fetching the whole user element, could this be related ?
Here's my code of how I'm doing this:
//User informations and password handling variables
profileForm!: FormGroup;
public userProfile$?: Observable<any>;
passwordUpdateSuccess = false;
profileUpdateSuccess = false;
public groupDetails?: any;
//Wish handling variables and functions
wishes: any[] = [];
public showUpdateForm: boolean = false;
updateWishForm!: FormGroup;
showUpdateFormFor: string | null = null;
//Handling wish filtering
public originalWishes: any[] = [];
public filterForm!: FormGroup;
ngOnInit(): void {
//Handling wishes
this.wishListService.secretSantaService.wishesSubject.subscribe(wishes => {
this.wishes = wishes;
});
this.updateWishForm = this.formBuilder.group({
title: ['', Validators.required],
url: ['', Validators.required],
description: ['', Validators.required],
price: ['', Validators.required],
});
// Fetch the user profile and update the relevant fields
this.userProfile$ = this.userService.getUserProfile();
// Update form and wishes when userProfile$ emits a new value
this.userProfile$.pipe(
tap(userProfile => {
this.profileForm.patchValue(userProfile);
this.wishes = userProfile.wishList;
this.originalWishes = userProfile.wishList;
})
).subscribe();
//Initialize the filter form control
this.filterForm = this.formBuilder.group({
minPrice: [''],
maxPrice: ['']
});
//Adding a time between each key put in the filter form to avoid too many requests
this.filterForm.valueChanges
.pipe(debounceTime(500))
.subscribe((filterValues) => this.filterWishes(filterValues));
}
addWish(wish: any) {
this.wishListService.addWishToUserWishList(wish).subscribe({
next: (newWish) => {
this.updateWishForm.reset();
this.showUpdateFormFor = null;
if (this.userProfile$)
this.userProfile$.subscribe(userProfile => {
this.updateAndFilterWishes(userProfile.wishList);
});
},
error: error => {
console.error(error);
}
});
}
submitUpdate(wishId: string) {
const updatedWish = this.updateWishForm.value;
this.wishListService.updateWishFromUserWishlist(wishId, updatedWish).subscribe({
next: updatedWish => {
this.showUpdateFormFor = null;
if (this.userProfile$)
this.userProfile$.subscribe(userProfile => {
this.updateAndFilterWishes(userProfile.wishList);
});
},
error: error => {
console.error(error);
}
});
}
deleteWish(wishId: string) {
this.wishListService.deleteWishFromUserWishlist(wishId).subscribe({
next: _ => {
this.showUpdateFormFor = null;
if (this.userProfile$)
this.userProfile$.subscribe(userProfile => {
this.updateAndFilterWishes(userProfile.wishList);
});
},
error: error => {
console.error(error);
}
});
}
getUserProfile(): void {
this.userService.getUserProfile().subscribe({
next: data => {
this.ngZone.run(() => {
if (this.profileForm)
this.profileForm.patchValue({
firstName: data.firstName,
lastName: data.lastName,
email: data.email,
dateOfBirth: data.dateOfBirth
});
});
console.log("data: ", data);
},
error: error => {
console.error(error);
return throwError(error);
}
});
}
Also, here the html :
<button mat-raised-button color="primary" (click)="openAddWishDialog()">Add Wish</button>
<!-- Update wishlist -->
<div class="flex items-center justify-center " *ngIf="userProfile$ | async as userProfile">
<div class="col-span-12">
<div class="overflow-auto lg:overflow-visible ">
<h3 class="text-2xl font-medium text-gray-700">
Your wish list
</h3>
<form [formGroup]="filterForm">
<input formControlName="minPrice" placeholder="Minimum price">
<input formControlName="maxPrice" placeholder="Maximum price">
</form>
<table class="table text-gray-400 border-separate space-y-6 text-sm">
<thead class="text-gray-500">
<tr>
<th class="p-3">Name</th>
<th class="p-3 text-left">Link</th>
<th class="p-3 text-left">Price</th>
<th class="p-3 text-left">Title</th>
<th class="p-3 text-left">Actions</th>
</tr>
</thead>
<tbody *ngFor="let wish of wishes">
<tr class="bg-gray-100 lg:h-32">
<td class="p-3">
<div class="flex align-items-center">
<div class="ml-3">
<div class="">{{wish.title}}</div>
</div>
</div>
</td>
<td class="p-3">
{{wish.url}}
</td>
<td class="p-3 font-bold">
{{wish.price}}
</td>
<td class="p-3">
{{wish.description}}
</td>
<td class="p-3">
<button type="submit" class="text-indigo-500 py-2 px-4 font-medium" (click)="toggleUpdateForm(wish.id)">
<i class="material-icons-outlined text-base"><svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24">
<path d="M180-180h44l443-443-44-44-443 443v44Zm614-486L666-794l42-42q17-17 42-17t42 17l44 44q17 17 17 42t-17 42l-42 42Zm-42 42L248-120H120v-128l504-504 128 128Zm-107-21-22-22 44 44-22-22Z"/></svg></i>
</button>
<button type="submit" class="text-gray-400 hover:text-gray-100 ml-2" (click)="deleteWish(wish.id)">
<i class="material-icons-round text-base"><svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24">
<path d="M261-120q-24.75 0-42.375-17.625T201-180v-570h-41v-60h188v-30h264v30h188v60h-41v570q0 24-18 42t-42 18H261Zm438-630H261v570h438v-570ZM367-266h60v-399h-60v399Zm166 0h60v-399h-60v399ZM261-750v570-570Z"/></svg></i>
</button>
</td>
</tr>
<tr class="bg-gray-800" *ngIf="showUpdateFormFor === wish.id">
<td colspan="6" class="p-3">
<form [formGroup]="updateWishForm" (ngSubmit)="submitUpdate(wish.id)">
<input formControlName="title" placeholder="Wish Name">
<input formControlName="url" placeholder="Wish Link">
<textarea formControlName="description" placeholder="Wish Description"></textarea>
<button type="submit">Update</button>
</form>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
答案1
得分: 0
你在一个非常不寻常的方式混淆了 Observables。以下是一些示例,展示了如何更好地处理它们:
// 不好,因为 tap 更适用于日志记录/调试/副作用
this.userProfile$.pipe(
tap(userProfile => {
this.profileForm.patchValue(userProfile);
this.wishes = userProfile.wishList;
this.originalWishes = userProfile.wishList;
}))
.subscribe();
// 更好地将“最终”操作写入 subscribe 区块
this.userProfile$
.pipe(take(1))
.subscribe(userProfile => {
this.profileForm.patchValue(userProfile);
this.wishes = userProfile.wishList;
this.originalWishes = userProfile.wishList;
});
// 不好,嵌套订阅
addWish(wish: any) {
this.wishListService.addWishToUserWishList(wish).subscribe({
next: (newWish) => {
this.updateWishForm.reset();
this.showUpdateFormFor = null;
if (this.userProfile$)
this.userProfile$.subscribe(userProfile => {
this.updateAndFilterWishes(userProfile.wishList);
});
},
error: error => {
console.error(error);
}
});
}
// 更好,链式组合 Observables 以减少复杂度并允许更好的取消
addWish(wish: any) {
this.wishListService.addWishToUserWishList(wish)
.pipe(
tap(() => {
this.updateWishForm.reset();
this.showUpdateFormFor = null;
}),
filter(() => this.userProfile != null),
switchMap(() => this.userProfile$)
)
.subscribe({
next: userProfile => this.updateAndFilterWishes(userProfile.wishList)),
error: error => console.error(error)
});
}
英文:
You mixing up the Observables in a very unusual way. Here are some examples how you do it better:
// bad because tap is more for logging/debugging/sideEffects
this.userProfile$.pipe(
tap(userProfile => {
this.profileForm.patchValue(userProfile);
this.wishes = userProfile.wishList;
this.originalWishes = userProfile.wishList;
}))
.subscribe();
// better write the "final" action into subscribe-block
this.userProfile$
.pipe(take(1))
.subscribe(userProfile => {
this.profileForm.patchValue(userProfile);
this.wishes = userProfile.wishList;
this.originalWishes = userProfile.wishList;
});
// bad nested subscriptions
addWish(wish: any) {
this.wishListService.addWishToUserWishList(wish).subscribe({
next: (newWish) => {
this.updateWishForm.reset();
this.showUpdateFormFor = null;
if (this.userProfile$)
this.userProfile$.subscribe(userProfile => {
this.updateAndFilterWishes(userProfile.wishList);
});
},
error: error => {
console.error(error);
}
});
}
// better chain observables together to reduce the complexity and allow better cancelation
addWish(wish: any) {
this.wishListService.addWishToUserWishList(wish)
.pipe(
tap(() => {
this.updateWishForm.reset();
this.showUpdateFormFor = null;
}),
filter(() => this.userProfile != null),
switchMap(() => this.userProfile$)
)
.subscribe({
next: userProfile => this.updateAndFilterWishes(userProfile.wishList)),
error: error => console.error(error)
});
}
I know, this not a direct answer to your problem. But your code is very hard to read and maybe this kind of refactoring already solves your problem.
答案2
得分: 0
好的,我找到了问题。
解决方案:
我有一个控制器,用于从用户调用所有元素,然后我将愿望清单链接到完全相同的可观察对象,这导致了这个...交互。
其他:
所以,我决定让我的代码更易维护(感谢 @akop!)并进行需求分离。
这导致了一个全新的组件,不受其他组件的干扰,保持简单!
英文:
Alright, i found the problem.
Solution :
I had a controller that was used to call every elements from a user, and i linked my wishlist to the exact same observable, which was causing this ... interaction
Other :
So, i've decided to make my code more maintainable (thanks @akop !) and to have a separation of needs.
Which led to a brand new component, not bothered by the other, keep it simple !
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论