【问题标题】:How to add item in rxjs observable array in angular如何在角度的rxjs可观察数组中添加项目
【发布时间】:2020-06-06 16:33:04
【问题描述】:

我有一个使用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);
  }
}

我的组件是:

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 ?

    }
}

我可以获取产品列表并使用 html 中的异步管道列出它们。但我无法在我的可观察数组中添加创建的项目。我该怎么做?

【问题讨论】:

  • 您在this.productService.add(item) 中缺少subscribe
  • @developer033 OP 正在恢复 observable 所以他们可能会在其他地方订阅它
  • @barteloma 请你看看我的回答对你有没有帮助?

标签: angular rxjs observable


【解决方案1】:

我不建议您考虑异步管道。

您可以通过创建不可观察的项目来满足您的需求。另外,不要忘记取消订阅 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()
   }

}

【讨论】:

    【解决方案2】:

    订阅可观察的项目 将新项目推入项目数组 将可观察的项目设置为可观察的更新项目

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

    【讨论】:

      【解决方案3】:
      1. 您可以使用rxjs#Subjectrxjs#mergerxjs#scan 来控制数据流,而不是每次在列表中执行操作(添加、删除、更新等)时重新分配items$
      2. 由于 Angular 9,ActivatedRoute#paramsdeprecated。请改用ActivatedRoute#paramMap
      3. 您不必手动订阅路由参数更改,只需使用 rxjs#switchMap 并执行以下操作:

      this.activatedRoute.paramMap.pipe( 地图(paramMap => paramMap.get('id')), switchMap(id => this.productsService.getItems(id)) )

      1. 您的服务方法中有错字: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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-17
        • 1970-01-01
        • 2018-03-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多