0

I have an angular service that consumes rest 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);
  }
}

And my component is:

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 ?

    }
}

I can get list of products and list them using async pipe in html. But I could not add the created item in my observable array. How can I do it?

3
  • You're missing the subscribe in this.productService.add(item). Commented Feb 22, 2020 at 14:07
  • @developer033 OP is returing the observable so they're probably subscribing to it elsewehere Commented Feb 22, 2020 at 14:08
  • @barteloma please, could you check if my answer helps you? Commented Feb 22, 2020 at 21:23

3 Answers 3

2
  1. Instead of reassigning the items$ every time you perform an operation in list (add, remove, update, etc.), you could use rxjs#Subject, rxjs#merge and rxjs#scan to control the data flow;
  2. You don't have to manually subscribe to route param changes, you could just use rxjs#switchMap and do something like this:

this.activatedRoute.paramMap.pipe( map((params) => params.id), switchMap((id) => this.productsService.getItems(id)) )

  1. You have a typo in a service method: caRegory :)

With these changes, we have this:

@Component({
  // ...
})
export class AppComponent {
  readonly items$: Observable<readonly Product[]>;
  private readonly insertedItemSource$ = new Subject<Product>();
  private readonly insertedItem$ = this.insertedItemSource$.asObservable();

  constructor(
    private readonly activatedRoute: ActivatedRoute, 
    private readonly productsService: ProductsService
  ) {      
    this.items$ = merge(          
      this.activatedRoute.params.pipe(
        map((params) => params.id),
        switchMap((id) => this.productsService.getItems(id))
      ),
      this.insertedItem$
    ).pipe(scan((accumulator, value) => [...accumulator, value]));
  }

  addWidget(): void {
    const item: Product = { color: 'purple', name: 'p-3' };
    this.productsService.add(item).subscribe(itemInserted => this.itemInsertedSource$.next(itemInserted));   
  }
}

STACKBLITZ DEMO

Sign up to request clarification or add additional context in comments.

Comments

-2

I would not suggest you to do it thought async pipe.

You can achieve your needs by creating not Observable items. Also, don't forget to unsubscribe from route params in ngOnDestroy method.

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()
   }

}

Comments

-2

subscribe to items observable push new item into items array Set items observable to observable of updated items

addWidget() {
    let item: any = {
        name: "p-1",
        color: "red"
    }
    this.productService.add(item));
    this.items.subscribe(items => {
        items.push(item);
        this.items = of (items);
    }
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.