Как добавить элемент в наблюдаемый массив rx js в angular - PullRequest
0 голосов
/ 22 февраля 2020

У меня есть angular служба, которая использует остальные API.

@Injectable({
  providedIn: 'root'
})
export class ProductService {

  private url: string = "/app/products";

  constructor(private http: HttpClient) {
  }

  get(caregoryId: string) {
    return this.http.get<Product[]>(`${this.url}`)
      .pipe(map(products => products.filter(p => p.caregoryId == caregoryId)))
  }

  add(p: Product) {
    return this.http.post<Product>(this.url, p);
  }
}

И мой компонент:

export class ProductComponent implements OnInit{

     items: Observable<Array<Product>>;

     ngOnInit() {
        this.route.params.subscribe(
          (params: any) => {
            this.items = this.productService.get(params.id);            
          })
     }

    addWidget() {
        let item: any = { name: "p-1", color: "red" } }

        this.productService.add(item))
        /// how to add created item in my items array ?

    }
}

Я могу получить список продуктов и перечислить их с помощью asyn c труба в html. Но я не мог добавить созданный элемент в свой наблюдаемый массив. Как я могу это сделать?

Ответы [ 3 ]

0 голосов
/ 22 февраля 2020

подписка на наблюдаемые элементы pu sh новый элемент в массиве элементов Установить элементы, наблюдаемые для наблюдаемых обновленных элементов

addWidget() {
    let item: any = {
        name: "p-1",
        color: "red"
    }
    this.productService.add(item));
    this.items.subscribe(items => {
        items.push(item);
        this.items = of (items);
    }
}
0 голосов
/ 22 февраля 2020
  1. Вместо переназначения items$ при каждом выполнении операции в списке (добавление, удаление, обновление и т. Д. c.) Вы можете использовать rxjs#Subject , rxjs#merge и rxjs#scan для управления потоком данных.
  2. С Angular 9, ActivatedRoute # params is устарело . Вместо этого используйте ActivatedRoute # paramMap ;
  3. Вам не нужно вручную подписываться на изменения параметров маршрута, вы можете просто использовать rxjs#switchMap и сделайте что-то вроде этого:

this.activationRoute.paramMap.pipe (map (paramMap => paramMap.get ('id')), switchMap (id => this.productsService). getItems (id)))

У вас есть опечатка в методе обслуживания: caRegory:)

С этими изменениями мы имеем:

@Component({
  // ...
})
export class AppComponent {
  readonly items$: Observable<readonly Product[]>;

  private readonly itemInsertedSource$ = new Subject<Product>();
  private readonly itemInserted$ = this.itemInsertedSource$.asObservable();

  constructor(
    private readonly activatedRoute: ActivatedRoute, 
    private readonly productsService: ProductsService
  ) {      
    this.items$ = merge(          
      this.activatedRoute.paramMap.pipe(
        map(paramMap => paramMap.get('id')),
        switchMap(id => this.productsService.getItems(id))
      ),
      this.itemInserted$
    ).pipe(scan((acc, value) => [...acc, value]));
  }

  addWidget(): void {
    const item: Product = { color: 'purple', name: 'p-3' };

    this.productsService.add(item).subscribe(itemInserted => this.itemInsertedSource$.next(itemInserted));   
  }
}

STACKBLITZ DEMO

0 голосов
/ 22 февраля 2020

Я бы не советовал вам делать это, как асин c труба.

Вы можете достичь своих потребностей, создав ненаблюдаемые предметы. Также не забудьте отписаться от параметров маршрута в методе ngOnDestroy.

export class ProductComponent implements OnInit, OnDestroy {
     id: string;
     items: Product[];
     subscription: Subscription;

     ngOnInit() {
       subscription = this.route.params
        .pipe(
          tap(params => this.id = params.id),
          switchMap(params => loadProducts(params.id))
        )
        .subscribe(
          (items: Product[]) => {
            this.items = items;            
          })


    loadProducts(id: string) {
        return this.productService.get(id);  
     }

    addWidget() {
        let item: any = { name: "p-1", color: "red" } }

        this.productService.add(item)).subscribe(result => {
          if (result) {
           this.items = [...this.items, item];
          } else {
             // notify error 
          }
        })

        // or if server updates item (puts new ids or some new data) then you need to fetch new data.

        this.productService.add(item))
          .pipe(switchMap(() => loadProducts(this.id)))
          .subscribe(items => {
             this.items = items;
          }
        })

    }

   ngOnDestroy() {
     this.subscription.unsubscribe()
   }

}
...