Я создаю интернет-магазин с некоторыми товарами. Пользователь может добавить в корзину и видеть добавленные им продукты. У меня три категории. Одна категория - это все продукты, в которых я отображаю все продукты и одну категорию фруктов и хлеба, где я показываю определенные продукты .. Все работает нормально, но когда я меняю категорию, не нажимая кнопку добавления в корзину, angular выполняет метод addToCart .. Я думаю, что это проблема с множественными подписками и утечкой памяти .. Как я могу сделать это с лучшим кодированием? Вот мои угловые файлы ts и html.
Мои продукты.
import {Component, OnDestroy, OnInit} from '@angular/core';
import {CategoryService} from '../category.service';
import {ActivatedRoute} from '@angular/router';
import {Subject} from 'rxjs/index';
import 'rxjs/add/operator/takeUntil';
import {ShoppingCartService} from '../services/shopping-cart.service';
import {Product} from '../models/product';
@Component({
selector: 'app-products',
templateUrl: './products.component.html',
styleUrls: ['./products.component.css'],
})
export class ProductsComponent implements OnInit, OnDestroy {
products: any;
filteredproducts: any;
category: any;
res: any;
categoryid: any;
cartId: any;
private ngUnsubscribe: Subject<any> = new Subject();
constructor(private service: CategoryService,
private route: ActivatedRoute,
private cartService: ShoppingCartService) {
}
ngOnInit() {
this.route.queryParamMap.takeUntil(this.ngUnsubscribe).subscribe(params => {
this.category = params.get('category');
this.cartId = localStorage.getItem('cartId');
if (this.category) {
setTimeout(() => {
this.service.allProductNames(this.category, this.cartId).takeUntil(this.ngUnsubscribe).subscribe(data => {
this.filteredproducts = this.products = data;
});
}, 500);
} else {
if (this.cartId === null) {this.cartId = -1; }
setTimeout(() => {
this.service.getProducts(this.cartId).takeUntil(this.ngUnsubscribe).subscribe(data => {
this.filteredproducts = data;
});
}, 500);
}
});
}
addToCart(products: Product) {
const cartId = this.cartService.getOrCreateCartId();
if (!cartId) {
const imero = new Date().getTime();
this.cartService.create(imero).takeUntil(this.ngUnsubscribe).subscribe(res => {
this.res = res;
localStorage.setItem('cartId', this.res.id);
this.route.queryParamMap.takeUntil(this.ngUnsubscribe).subscribe(params => {
this.categoryid = params.get('category');
if (this.categoryid) {
this.cartService.createItem(products.id, this.res.id).
takeUntil(this.ngUnsubscribe).subscribe(res1 => {
setTimeout(() => {
this.service.allProductNames(this.category, this.res.id).takeUntil(this.ngUnsubscribe).subscribe(data => {
this.filteredproducts = this.products = data;});
}, 500);
});
} else {
this.cartService.createItem(products.id, this.res.id).takeUntil(this.ngUnsubscribe).subscribe(res2 => {
setTimeout(() => {
this.service.getProducts(this.res.id).takeUntil(this.ngUnsubscribe).subscribe(data => {
this.filteredproducts = data;
});
}, 500);
} );
}
});
});
}
else {
this.route.queryParamMap.takeUntil(this.ngUnsubscribe).subscribe(params => {
this.categoryid = params.get('category');
this.cartId = localStorage.getItem('cartId');
if (this.category) {
this.cartService.createItem(products.id, this.cartId).takeUntil(this.ngUnsubscribe).subscribe(res1 => {});
setTimeout(() => {
this.service.allProductNames(this.category, this.cartId).takeUntil(this.ngUnsubscribe).subscribe(data => {
this.filteredproducts = data;
});
}, 500);
} else {
this.cartService.createItem(products.id, this.cartId).takeUntil(this.ngUnsubscribe).subscribe(res1 => {});
setTimeout(() => {
this.service.getProducts(this.cartId).takeUntil(this.ngUnsubscribe).subscribe(data => {
this.filteredproducts = data;
console.info(this.products);});
}, 500);
}
});
}
}
ngOnDestroy() {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}
}
Мои продукты.html
<div class = "row">
<div class = "col-sm-3">
<app-product-filter></app-product-filter>
</div>
<div class = "col-sm-9">
<div class = "row">
<ng-container *ngFor = "let p of filteredproducts; let i = index">
<div class = "col">
<div class = "card">
<img class = "card-img-top" src = "{{p?.imageUrl}}" style = "max-height: 200px; width: 100%;">
<div class = "card-body">
<h5 class = "card-title">{{p?.title}}</h5>
<p class = "card-text">{{p?.price | currency: 'EUR': symbol }}</p>
</div>
<div class = "card-footer">
<button (click) = "addToCart(p)" class = "btn btn-primary btn-block">Add to Cart</button>
<div *ngIf = "p?.quantity!=0">{{p?.quantity}}</div>
</div>
</div>
</div>
<div *ngIf = "(i+1) % 2 === 0" class = "w-100"></div>
</ng-container>
</div>
</div>
</div>





Вы никогда не должны подписываться на подписку. Вы можете изменить свой код следующим образом:
this.route.queryParamMap.mergeMap(params => {
this.category = params.get('category');
this.cartId = localStorage.getItem('cartId');
if (this.category) {
return this.service.allProductNames(this.category, this.cartId);
} else {
if (this.cartId === null) {
this.cartId = -1;
}
return this.service.getProducts(this.cartId);
}
}).takeUntil(this.ngUnsubscribe).subscribe(data => this.filteredproducts = data);
Вы должны подписаться на свой queryParams только один раз, и он должен быть в ngOnInit. При добавлении в корзину вы должны учитывать следующие моменты:
я починил .. Большое спасибо за вашу помощь
Спасибо :) Я пытаюсь исправить метод addToCart, но с mergeMap, а код внутри не работает .. Моя программа не входит внутрь .. Я следую той же логике .. Внутри ngOnInit все в порядке, но за пределами mergeMap, похоже, не работает :(