TypeError: Cannot read property 'pipe' of undefined

32,358

There are more than 1 thing that are not right with what you are asking.

First, you are passing a Subject and expecting an Observable. This is why you are getting error

TypeError: Cannot read property 'pipe' of undefined

Then, you are passing Subject as term (I assume you want to send search keyword).

You don't need a Subject in your situation. You can do it like this:

Template:

<input type='text' class="form-control input-txt-start" placeholder="Search Domain Name" name="domainId" (keyup)='getSearchResults($event)'>  <---- Send only $event here

Component:

getSearchResults(event) {
    this.searchService.search(event.target.value).subscribe((res) => { // <--- Get target value of event
      console.log(res);
      this.results = res;
    }, err => {
      console.log(err);
      this.error = err.message;
    });
  }
}

Service:

search(term) {  // <--- Notice that the parameter name became term instead of terms

    // You can use of() method of RxJS
    // You need to import of with "import { of } from 'rxjs';"
    // You can chain you operators in pipe() method with commas

    return of(term).pipe(
       debounceTime(500),
       distinctUntilChanged(),
       switchMap(() => this.searchEntries(term) // <--- Notice that, this function has no parameter
     );
  }
Share:
32,358
Ram
Author by

Ram

Updated on June 11, 2020

Comments

  • Ram
    Ram almost 4 years

    I'm writing a real-time search functionality in Angular with RxJS. I'm getting some error as TypeError: Cannot read property 'pipe' of undefined. I'm using Angular 7 and I have tried different code samples from StackOverfloew, but couldn't fix this issue.

    app.Component.html

    <input type='text' class="form-control input-txt-start" placeholder="Search Domain Name" name="domainId" (keyup)='getSearchResults(searchTerm$.next($event.target.value))'>
    
    <ul *ngIf="results">
        <li *ngFor="let result of results | slice:0:9">
            {{ result}}
        </li>
    </ul>
    <p *ngIf="error">
        {{error}}
    </p>
    

    app.component.ts

    import { Component, OnInit, ViewChild } from '@angular/core';
    import { FormBuilder, FormGroup, Validators, NgForm, FormControl } from '@angular/forms';
    import { SearchService } from 'src/app/services/search.service';
    import { Subject } from 'rxjs';
    
    @Component({
      ...
      providers: [SearchService]
    })
    
    export class AppComponent implements OnInit { 
      results: Object;
      searchTerm$: any = new Subject();
      error: any;
    
      constructor(private searchService: SearchService) { }
    
      ngOnit() { }
    
      getSearchResults(search) {
        this.searchService.search(search).subscribe((res) => {
          console.log(res);
          this.results = res;
        }, err => {
          console.log(err);
          this.error = err.message;
        });
      }
    }
    

    search.service.ts

    import { Injectable } from '@angular/core';
    import { HttpClient, HttpHeaders } from '@angular/common/http';
    import { Observable } from 'rxjs';
    import { debounceTime } from 'rxjs/operators';
    import { distinctUntilChanged } from 'rxjs/operators';
    import { map } from 'rxjs/operators';
    import { switchMap } from 'rxjs/operators';
    import { environment } from '../../environments/environment';
    
    @Injectable({
      providedIn: 'root'
    })
    
    export class SearchService {
      public httpOptions = {
        headers: new HttpHeaders({'Content-Type': 'application/json'})
      };
    
      baseUrl: String = `${environment.API_URL}/api/domainCharts`;
      queryUrl: String = '?search=';
    
      constructor( private http: HttpClient ) { }
    
      search(terms: Observable<string>) {
        return terms.pipe(debounceTime(500)).pipe(distinctUntilChanged()).pipe(switchMap(term => this.searchEntries(term)));
      }
    
      searchEntries(term) {
        return this.http.get(`${this.baseUrl}${this.queryUrl}${term}`);
      }
    }
    
  • Ram
    Ram almost 5 years
    When I changed as per your suggestion as below, ` search(term) { return terms.pipe(debounceTime(500), distinctUntilChanged(), switchMap(() => this.searchEntries(term))); } ` 1. In return statement, if it is terms, it says Cannot find name 'terms' 2. In return statement, if I change it to term, it says TypeError: term.pipe is not a function
  • Harun Yilmaz
    Harun Yilmaz almost 5 years
    Updated the answer. You could use of() method of RxJS: learnrxjs.io/operators/creation/of.html
  • Harun Yilmaz
    Harun Yilmaz almost 5 years
    But this way, distinctUntilChanged() becomes meaningless as you create a new observable every time this function is fired. I think you need to move debounce and distinctUntilChanged to component file. Maybe you can use fromEvent of RxJS to achieve this: learnrxjs.io/operators/creation/fromevent.html
  • Ram
    Ram almost 5 years
    Thanks a ton @Harun, it worked for me. I will try by moving debounce and distinctUntilChanged and using fromEvent of RxJS and let you know.