0

I'm trying to iterate my results in my ngFor - it's not so intuitive like Angular 1. I've the following:

search.service.ts

import {Injectable} from 'angular2/core';
import {Http, HTTP_PROVIDERS, Response} from 'angular2/http';
import 'rxjs/add/operator/map';

@Injectable()
export class SearchService {

  constructor( private _http: Http ) {

  }

  DoGeneralSearch(s){   
    return this._http.get('http://localhost:6000/search?q=' + s)
     .map((res:Response) => res.json())
  } 
} 

typeahead.ts

import {Component, Input, OnChanges} from "angular2/core";
import {SearchService} from "../../../services/search.service";

@Component({
  selector: "typeahead",
  providers: [SearchService],
  template : `
    <div>{{searchSvc | async | json}}</div>
    <div id="typeaheadRooms" *ngIf="searchSvc">
      <div class="typeaheadRowRooms" *ngFor="#item of searchSvc?.rooms">
        <div class="typeaheadRoomTitle">{{item.name}}}</div>
      </div>
      <div class="typeaheadRowRooms" *ngFor="#item of searchSvc?.colors">
        <div class="typeaheadRoomTitle">{{item.name}}}</div>
      </div>
`,
})
export class TypeaheadComponent implements OnChanges {

  @Input() txt: string;
  display = false;

  ngOnChanges(changes: {[propName: string]: SimpleChange}) {
    var search = changes['txt'].currentValue;
    if(search.length > 2) {
        this.display = true;
        this.searchSvc = this._searchService.DoGeneralSearch(search);
    }
    else
    {
        this.display = false;
    }
  }

  constructor(private _searchService: SearchService) {}
}

a typical results in json :

{  
"max":20,
"queryString":"chem",
"rooms":[  
  {  
     "name":"Lima"
  },
  {  
     "name":"Delta"
  }
 ],
"colors":[  
  {  
     "name":"Red"
  },
  {  
     "name":"Lime"
  }
 ]

}

What's happening ? Well, {{searchSvc | async | json}} show me results. But the ngFor: No :(

Any clues? thank you in advance !!!

Poul Kruijt
  • 69,713
  • 12
  • 145
  • 149
Marco Jr
  • 6,496
  • 11
  • 47
  • 86
  • Possible duplicate of [Iterate through json string in Observable angular js 2](http://stackoverflow.com/questions/35339411/iterate-through-json-string-in-observable-angular-js-2) – Günter Zöchbauer Mar 10 '16 at 11:11
  • No, Gunter...does not apply to my situation. But thanks because I bookmarked that post - Will be very useful in the future – Marco Jr Mar 10 '16 at 11:24

1 Answers1

1

In this case, you need to use this:

<div class="typeaheadRowRooms" *ngFor="#item of searchSvc | async">

and update your service like this:

DoGeneralSearch(s){   
  return this._http.get('http://localhost:6000/search?q=' + s)
     .map((res:Response) => res.json().rooms);
}

Edit

If you want to receive the full object from the observable, I see two ways to do that:

  • Explicit subscribe:

    this._searchService.DoGeneralSearch(search).subscribe(
      (data) => {
        this.searchSvc = data;
      }
    );
    

    and in the template

    <div class="typeaheadRowRooms" *ngFor="#item of searchSvc?.rooms">
    
  • Custom pipe to get the rooms data:

    @Pipe({name: 'field'})
    export class FieldPipe implements PipeTransform {
      transform(value, args:string[]) : any {
        return value[args[0]];
      }
    }
    

    and in the template

    <div class="typeaheadRowRooms" *ngFor="#item of searchSvc | async | field:rooms">
    
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • Hi again, Therry ;) Well..I edited the result...it can return rooms or colors in fact. if I set this on the service..I will restrict myself just to grab the rooms array :( Just for curious I set in this fashion to test your async on the ngFor and it's works..but I really need to iterate in different keys.... – Marco Jr Mar 10 '16 at 11:23
  • Almost there ! I just added: import "Pipe, PipeTransform} from "angular2/core" , @ component....pipes: [FieldPipe]....@ pipe(....) , @ export class FieldPipe (....) and this still throw me a No Directive annotation found on TypeaheadComponent - Something missing ? – Marco Jr Mar 10 '16 at 12:12
  • It seems that a `@Component` annotation is missing on your `TypeaheadComponent` component... Could you give me the corresponding code? – Thierry Templier Mar 10 '16 at 12:14
  • sure ! [typeahead]: import {FieldPipe} from '../../_generics/field-pipe.component';______ @Component({ selector: "typeahead", providers: [SearchService], pipes: [FieldPipe]... template : `
    {{item.name}}
    ` ____ export class TypeaheadComponent (...) this.searchSvc = this._searchService.DoGeneralSearch(search).subscribe( (data) => { this.searchSvc = data; } ); [field-pipe-component] : import and @pipe and expor
    – Marco Jr Mar 10 '16 at 12:38
  • I placed your pipe in a different file now...now it's throw me EXCEPTION: Invalid argument '[object Object]' for pipe 'AsyncPipe' in [searchSvc | async | field:rooms in TypeaheadComponent@15:43] – Marco Jr Mar 10 '16 at 12:38
  • nvmd ! I reviewd !! now it's working !! get another "Answered" from me ! U r a star, Thierry ! – Marco Jr Mar 10 '16 at 12:43