3

I'm working on implementing a search functionality via Angular2/TypeScript.

I'm having some trouble binding the search items returned to the view however.

My component is this:

import { Component } from '@angular/core';
import { SearchService } from '../services/search.service';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import "rxjs/add/operator/debounceTime";
import "rxjs/add/operator/distinctUntilChanged";
import 'rxjs/add/operator/switchMap';

@Component({
  selector: 'search',
  templateUrl: './app/views/search.component.html',
  providers: [SearchService]
})

export class SearchComponent {
  items: Observable<string[]>;
  errorMsg: string;

  private searchTermStream = new Subject<string>();

  searchConfluence(term : string) {
    // Send the search term into the Observable stream
    this.searchTermStream.next(term);
  }

  ngOnInit(): void {
    this.items = this.searchTermStream
      .debounceTime(300)
      .distinctUntilChanged()
      .switchMap(term => this.searchService.titleSearch(term));
  }

  constructor(private searchService: SearchService) {}
}

My view is the following:

<h1>Search</h1>
<input #term (keyup)="searchConfluence(term.value)" />
<ul style="list-style: none">
  <li *ngFor="let item of items | async">
    {{item.title}}
  </li>
</ul>

My search service:

import { Injectable } from '@angular/core';
import { Http, Response, Headers, RequestOptions } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';

@Injectable()
export class SearchService {

  private searchUrl = URL_HERE;

  constructor(private http: Http) {}

  titleSearch(params: string): Observable<string[]> {
    let options = new RequestOptions({ headers: this.header});
    let requestString = `term=${params}`;
    return this.http.get(`${this.searchUrl}?${requestString}`, options)
      .map(this.getData)
      .catch(this.handleError);
  }

  private getData(resp: Response) {
    let body = resp.json();
    console.log(body.results);
    return body.results || [];
  }

  private handleError(error: Response | any) {
    let errMsg: string;
    if (error instanceof Response) {
      const body = error.json() || '';
      const err = body.error || JSON.stringify(body);
      errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
    } else {
      errMsg = error.message ? error.message : error.toString();
    }
    return Observable.throw(errMsg);
  }
}

The response returned by the server is following:

 [Object, Object ... ]

where each Object is a JSON object. This is what I'm expecting as a response.

I've checked the network trace and the HTTP request is firing to the correct place and I'm getting results back as well (again, all viewed through the network trace). I'm unable to view the any results in my view (the list just doesn't appear at all).

EDIT: One last edit, but I might have left out a crucial detail; my Angular2 application isn't inside a typical browser, but actually contained within an ElectronJS application. I'm not sure if that makes any difference.

docaholic
  • 613
  • 9
  • 29

1 Answers1

0

After one day of just fiddling around, I got the answer to this question.

It looks like Electron's API doesn't update as quickly as a web browser does so I followed the solution found in here.

Basically I'm doing this in my search.component.ts class:

ngOnInit(): void {
  this.searchTermStream
    .debounceTime(300)
    .distinctUntilChanged()
    .switchMap(term => this.searchService.titleSearch(term))
    .subscribe((result) => { 
      this.items = result;
      this.cdRef.detectChanges();
    });
  }

And voila, everything is updating correctly, and I have a nice list of my search results :).

Community
  • 1
  • 1
docaholic
  • 613
  • 9
  • 29