【问题标题】:Angular removing elements from a list shared with a service从与服务共享的列表中删除元素
【发布时间】:2021-01-31 03:36:36
【问题描述】:

这个问题快把我逼疯了。

我在服务中定义了一个数组,该数组用于其他 3 个组件:

这是服务,文件 products.service.ts(注意 Products 的产品数组)

import { Injectable } from '@angular/core';
import { ​​HttpClient } from '@angular/common/http';

import { Product } from './../models/Product';
import { ProductForm, productFormToProduct } from './../models/ProductForm';


// @Injectable({
//   providedIn: 'root'
// })

const apiUrl = 'http://localhost:3000/products';

@Injectable()

export class ProductsService {

  public products: Product[] = [];

  constructor(private http: HttpClient) {}

  getProducts() {
    return this.http.get(apiUrl)
  }

  deleteProduct(p: Product) {
    // this.products = this.products.filter(prod => prod.id !== p.id);
    const i = this.products.indexOf(p);
    this.products.splice(i,1);
    return this.http.delete(apiUrl + "/" + p.id)
  }

  storeNewProduct(pf: ProductForm) {
    const idList = this.products.map((x) => {return x.id});
    const i = Math.max(...idList) + 1;
    const p = productFormToProduct(pf);
    p.id = i;
    this.products.push(p);
    return this.http.post(apiUrl, p)
  }

}

这是我订阅 getProducts 的组件,并填充数组(文件 products.component.ts):

import { Component, OnInit } from '@angular/core';

import { ProductsService } from '../../shared/services/products.service';
import { Product } from '../../shared/models/Product';


@Component({
  selector: 'app-products',
  templateUrl: './products.component.html',
  styleUrls: ['./products.component.scss']
})
export class ProductsComponent implements OnInit {

  products: Product[] = [];
  searchText: string = "";

  constructor(private productsService: ProductsService) {}

  ngOnInit(): void {
    this.productsService.getProducts()
      .subscribe((data: Product[]) => {
        this.productsService.products = data;
        this.products = this.productsService.products;
      })
  }

}

这是我订阅 deleteProduct 的组件(文件 product-card.component.ts):

import { Component, Input, OnInit } from '@angular/core';

import { ProductsService } from '../../services/products.service';
import { Product } from './../../models/Product';

@Component({
  selector: 'app-product-card',
  templateUrl: './product-card.component.html',
  styleUrls: ['./product-card.component.scss']
})
export class ProductCardComponent implements OnInit {

  constructor(private productsService: ProductsService) {}

  ngOnInit(): void {
  }

  @Input() product: Product

  public buttonDeleteFunction() {
    this.productsService.deleteProduct(this.product).subscribe();
  }


}

问题是,当我点击一些删除产品按钮时,我有这种奇怪的行为:

点击前:

点击后:

这是 products.component.html 文件:

<div class="products__header">
  <h3 class="products__heading">
    Listado de productos ({{ products.length }})
  </h3>
  <input
    class="products__search"
    placeholder="Buscador"
    type="search"
    [(ngModel)]="searchText"
  />
</div>

<p *ngFor="let p of products">{{ p.name }}</p>
<p>{{ products }}</p>

<div class="products__list">
  <app-product-card
    *ngFor="let p of products | filterNames: searchText"
    [product]="p"
  ></app-product-card>
</div>

为什么在我使用产品列表的四个地方中,我只在两个地方得到了预期的行为?

我知道当我单击按钮时,我可以使用输出手动从列表中删除项目,但是当我想在多个组件之间共享时,我被告知使用服务而不是输入/输出,所以我' d 而不是为此使用输出

【问题讨论】:

    标签: javascript angular concurrency


    【解决方案1】:

    当您在服务层上使用您的方法处理公共数据时,一个常见的缺陷是 Angular 不会检测到影响您的组件的更改。在这种情况下,您必须使用 emmiter 通知您的组件进行这些更改。

    在服务上使用 emmiter

       productUpdated :EventEmitter = new EventEmitter();
    
     deleteProduct(p: Product) {
        // this.products = this.products.filter(prod => prod.id !== p.id);
        const i = this.products.indexOf(p);
        this.products.splice(i,1);
    
        this.productUpdated.emit(this.products);
    
        return this.http.delete(apiUrl + "/" + p.id)
      }
    

    然后监听 ProductsComponent 的变化

    export class ProductsComponent implements OnInit {
    
      products: Product[] = [];
      searchText: string = "";
    
      constructor(private productsService: ProductsService) {}
    
      ngOnInit(): void {
        this.productsService.getProducts()
          .subscribe((data: Product[]) => {
            this.productsService.products = data;
            this.products = this.productsService.products;
          })
        this.productsService.productUpdated.subscribe( (data) => { 
          this.products = data;
          });
      }
    

    【讨论】:

    • 完美,这行得通!我接受并赞成你的回答。但是,我仍然不明白为什么有些 html 反映了这种变化,而另一些则没有反映在我之前的代码中。
    猜你喜欢
    • 2012-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-25
    • 2017-03-05
    相关资源
    最近更新 更多