1

It seems like everything is fetched correctly, but i still cannot render result of http request in view. Here goes.

This is my category service :

@Injectable()
export class CategoryService {

private _category : BehaviorSubject<any> = new BehaviorSubject([]);

public category : Observable<Category> = this._category.asObservable();

constructor(private myHttpService : HttpService){ }


 public getCategory(id : String) : void {
 let params = new URLSearchParams();
 params.append('id', `${id}`);

 this.myHttpService.get(Constants.catalog+"/category",params)
                               .map(res =>res.json())
                               .subscribe(categoryJson => {
                                  const category = Category.fromJson(categoryJson);
                   console.log(category) //<- this prints category object correctly

                                 //update BehaviorSubject
                                 this._category.next(category);
                               });
 } 
 }

This is my category component :

export class CategoryComponent implements OnInit {

private category : Observable<Category>;

constructor(private categoryService : CategoryService) {
this.category = categoryService.category;
     console.log(this.category)// <-- this prints  Observable { _isScalar=false,  source=BehaviorSubject,  lift=function(),  more...} 
     //when i drill down i can find category object under source/value
} 

ngOnInit() {
 this.categoryService.getCategory('2002');
  }
}

This is my category view :
I have experimented here a lot : 1.Wrapped category in array and used for with async pipe 2.Used elvis operator to display category?.name (btw this works for promise, bot not observable)

<div class="ui divided items">
     <app-product-list [products]="category?.products"></app-product-list>
</div>

This also doesnt work

<p> {{category?.title}}</p>

This is my product-list component :

 export class ProductListComponent implements OnInit {

 @Input()
 private products : Product[];

 constructor() {}

 ngOnInit() {
 console.log(this.products); // this is always undefined
 }
 }

This is my view product-list view:

<div class="container">
<app-product
  *ngFor="let product of products | async"
  [product]="product"
  class='item'></app-product>
 </div>

And finally this is my Product-component

export class ProductComponent implements OnInit {

    @Input()
    private product : Product;

    constructor() { }

    ngOnInit() {}

}

And my Product view :

<p>
product works! {{product?.title}}

1
  • 2
    You have the async pipe in the wrong place. If the list component should receive an array of products, the observable should have been resolved before it even gets called. Commented Nov 7, 2016 at 7:41

1 Answer 1

2

I would change it like:

return the observable from `getCategory()´ directly

public getCategory(id : String) : void {
  let params = new URLSearchParams();
  params.append('id', `${id}`);

  return this.myHttpService.get(Constants.catalog+"/category",params)
                               .map(res =>res.json())
                               .map(categoryJson => Category.fromJson(categoryJson);
  });
} 

assign the result from getCategory to the local variable

export class CategoryComponent implements OnInit {

  private category : Observable<Category>;

  constructor(private categoryService : CategoryService) {}

  ngOnInit() {
    this.category = this.categoryService.getCategory('2002');
  } 
}

Use it like

<p> {{(category | async)?.title}}</p>
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks. Works like a charm. On the side note, should i pass in observable to nested component or should i somehow wait for observable to be resolved before rendering <app-product-list> component? What is the best practise here? Right now if i just pass <app-product-list [products]="category.products"></app-product-list> products is always undefined. I have naively tried <app-product-list [products]="(category | async)?.products"></app-product-list> but doesnt work :)
<app-product-list [products]="(category | async)?.products"></app-product-list> should work. Do you get an error? What do you get for <div>{{category | async | json}}</div>?
Actually it does work. I have removed async pipe from *ngFor, as @jonrsharpe already mentioned, and corrected a small typo. Now everything works as expected. You sire have made my day. Thanks again.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.