Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2: TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined

I'm new to observables and experimenting with an basic autocomplete variation of Christoph Burgdorf's Observables in Angular2 blog. Running this code produces:

EXCEPTION: TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined

after issuing the REST get call in ingredientservice...rawsearch. The alert also pops with an [object Object] message. I've verified the endpoint is running fine.

Any recommendations on how to debug this would be greatly appreciated.

ingredientservice.ts waits for a change on a text string, debounces it and performs a REST call to get autocomplete matches from an endpoint.

import {Injectable} from 'angular2/core';
import {Http} from 'angular2/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/map';

@Injectable()
export class IngredientService {
  endpoint_url: String = "http://localhost:5000/ingredient/";
  results: Observable<Array<string>>;
  constructor(private http: Http) { }

  search(terms: Observable<string>, debounceDuration = 400) {
    return terms.debounceTime(debounceDuration)
      .distinctUntilChanged()
      .switchMap(term => this.rawSearch(term));
  }

  getData: Object[];
  rawSearch(term: string) {
    console.log(term);

    this.http.get(this.endpoint_url + term)
      .subscribe(
      res => {
        this.getData = res.json();
        console.log(this.getData);
        return this.getData;
      },
      error => alert(error));
  }
}

for completeness I have included the component ingredientsearch.ts

import {Component} from 'angular2/core';
import {Control} from 'angular2/common';
import {IngredientService} from './ingredientservice';
import {Observable} from 'rxjs/Observable';

@Component({
  selector: 'ingredient-search',
  template: `
    <div>
      <h2>Ingredient Search</h2>
      <input type="text" [ngFormControl]="term"/>
      <ul>
        <li *ngFor="#item of items | async">{{item}}</li>
      </ul>
    </div>
  `,
  providers: [IngredientService]
})

export class IngredientSearch {
  items: Observable<Array<string>>;
  term = new Control();
  constructor(private ingredientService: IngredientService) {
    console.log("About to call service");
    this.items = ingredientService.search(this.term.valueChanges);
  }
}

Updated code snippet with recommended fix.

rawSearch(term: string) {
    this.getData = ([]);
    this.http.get(this.endpoint_url + term)
      .subscribe(
      res => {
        this.getData = res.json();
        console.log(this.getData);
        return this.getData;
      },
      error => {
        alert(error);
      });
    return this.getData;
  }
like image 361
Tim W. Avatar asked Mar 29 '16 21:03

Tim W.


1 Answers

Items is undefined when the view is bound - before the service returns. Initialize items to an empty array. Or use an Observable wrapper and the async operator in your template.

like image 115
KnowHoper Avatar answered Oct 21 '22 20:10

KnowHoper