1

ok. I'm trying to add some methods to model class of an object which is streaming in observable, I want for example to multiply two propoerties and return result in that new property. This is working when data stream is displayed through async pipe, but how can I do this with normal subscribed observable? I tried to return getter through async - await but that is not working

export interface IProduct {
  price: number;
  tax: string;
}

export class Product implements IProduct {
  constructor(
    public price: number,
    public tax: string,

  ) { }


  get grossPrice() {
    return this.price * parseInt(this.tax)
  }
}


export class ProductService {

   private url = ''

  constructor(private http: HttpClient){ }

  getAll(): Observable<Product[]> {
    return this.http.get<Product[]>(this.url)
}
}


@Component({
  template: `<div *ngFor="let product of products">
               {{ product.grossPrice }}
                </div>
              `
})
export class ProductsViewComponent implements OnInit, OnDestroy {
  products: Product[] = [];

constructor(private productService: ProductService){}
  this.productService
      .getAll()
      .subscribe(data => this.products = data)
}
peter 73
  • 85
  • 1
  • 8
  • 2
    Please provide the code that demonstrates what you try to accomplish, what you tried and where you failed. – Günter Zöchbauer Mar 09 '18 at 11:06
  • code added ..... – peter 73 Mar 09 '18 at 11:19
  • That would not transpile, you can't have a call to something listed as a member *and* it is using a `productService` which does not exist as a member. How does this class begin to relate to your component? What are you trying to do? The above does not really make any sense when read with your description. – Igor Mar 09 '18 at 11:26
  • 1
    `This is working when data stream is displayed through async pipe` <= at least provide that code that you state is working and start from there. – Igor Mar 09 '18 at 11:28
  • I've corrected the code, hope that is clearer now – peter 73 Mar 09 '18 at 11:45
  • @peter73 - If the following answers your question please consider marking it accordingly using a check-mark on the left side of the answer. – Igor Mar 09 '18 at 12:34

1 Answers1

1

Here is code that will compile. You need a couple of fixes.

  1. You need to transform the returned IProduct from the HttpClient call into a class instance Product. This is done using Pipeable Operators, see also so - In Angular rxjs when should I use pipe vs map.
  2. You need to call the service in ngOnInit, not the constructor of the component.
  3. I provided 2 components, one uses an async pipe and the other uses subscribe.

ProductService.ts

import { Observable } from 'rxjs/observable';
import { map } from 'rxjs/operators/map';
import { HttpClient } from '@angular/common/http';

export interface IProduct {
    price: number;
    tax: string;
}

export class Product implements IProduct {
    constructor(public price: number, public tax: string) {
    }

    get grossPrice() {
        return this.price * parseInt(this.tax);
    }
}

export class ProductService {
    private url = '';

    constructor(private http: HttpClient) { }

    getAll(): Observable<Product[]> {
        return this.http.get<IProduct[]>(this.url)
            .pipe(map((products) => {
                return products.map(p => new Product(p.price, p.tax));
            }));
    }
}

ProductsViewComponent.ts

Component that subscribes to the observable and assigns the result to a field.

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

@Component({
    template: `<div *ngFor="let product of products">
                 {{ product.grossPrice }}
               </div>`
})
export class ProductsViewComponent implements OnInit {
    products: Product[] = [];

    constructor(private productService: ProductService) { }

    ngOnInit() {
        this.productService
            .getAll()
            .subscribe(data => this.products = data);
    }
}

ProductsViewAsyncPipeComponent.ts

Component that uses an async pipe.

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs/observable';
import { Product, ProductService } from './ProductService;

@Component({
    template: `<div *ngFor="let product of products | async">
                 {{ product.grossPrice }}
               </div>`
})
export class ProductsViewAsyncPipeComponent implements OnInit {
    products: Observable<Product[]>;

    constructor(private productService: ProductService) { }

    ngOnInit() {
        this.products = this.productService.getAll();
    }
}
Igor
  • 60,821
  • 10
  • 100
  • 175