Gabriel
Gabriel

Reputation: 391

Angular 5 typeerror:

I am using Angular 5 in a project and i get a typescript error:

ERROR TypeError: Cannot read property 'indexOf' of undefined

What my code is supposed to do is to update the template on input change like this:

The template:

<input #f (input)="filterResults(f.value)"/>

<div *ngIf="filteredCandidates.length">
    <ul class="filtered-candidates-list">
        <li *ngFor="let candidate of filteredCandidates">
            {{ candidate.name }}
        </li>
    </ul>
</div>

And the component.ts:

  private queryString: string;
  private candidates: Candidate[] = []
  private filteredCandidates: Candidate[] = [];

  filterResults(queryString) {
    this.candidatesService.filterCandidates().subscribe(candidates => this.candidates = candidates);
    if (!queryString) {
      return;
    }
    else {
      this.candidates.filter(c => { c.name.indexOf(queryString) >= 0 });
    }
  }

I tried using the method .contains() on the c.name, and got the same result. The typeof candidate.name is still string, as expected, as well as the input which is also a string. However, it is like i can't use the string methods just due to typescript being incorporated.

Upvotes: 3

Views: 1135

Answers (3)

Pankaj Parkar
Pankaj Parkar

Reputation: 136184

It seems like you're trying to perform filter operation on collection candidates even though it haven't been retrieved from the API server yet. By looking at your UI, it doesn't look like you are peforming any remote filtering based on query string. In this case I'd recommend to retrieve the candidates collection at the start and untill then make input box disabled/readonly. So that will avoid unexpected error to happen.

HTML

<input #f (input)="filterResults(f.value)" [readonly]="candidates.length"/>

<div *ngIf="filteredCandidates.length">
    <ul class="filtered-candidates-list">
        <li *ngFor="let candidate of filteredCandidates">
            {{ candidate.name }}
        </li>
    </ul>
</div>

Component

private queryString: string;
private candidates: Candidate[] = []
private filteredCandidates: Candidate[] = [];

getResults(){
    this.candidatesService.filterCandidates().subscribe(
       candidates => this.candidates = candidates || []
    );
};

filterResults(queryString) {
    if (!queryString) {
      return;
    }
    else {
      this.candidates.filter(c => { c.name && c.name.indexOf(queryString) >= 0 });
    }
}

Upvotes: 1

Gabriel
Gabriel

Reputation: 391

What a foolish mistake. I had to do some error handling. In the database, one of the objects had no property name (undefined). So when the loop got there, the code broke. I have to handle errors better. Thank you all for suggestions though.

Upvotes: 0

Lucas
Lucas

Reputation: 10313

If c.name is not defined in some cases, you could do the check like this:

  this.candidates.filter(c => { 
      return c.name !== null && c.name.indexOf(queryString) >= 0 
  });

Here, !== null will check for both null and undefined values.

Upvotes: 1

Related Questions