angularpipes-filters

angular 2. Pipes. Cannot read property of undefined


i made a pipe

@Pipe({
  name: 'orgFilter'
})
export class OrgFilterPipe implements PipeTransform {
    transform(orgs: Organization[], args: String[]): any {
        console.log(orgs)
       let filter = args[0].toLowerCase();
       return filter ? orgs.filter((org:Organization) => org.name.toLowerCase().indexOf(filter) != -1): orgs;
}

and using it in html:

<tbody>
        <tr *ngFor="#organization of organizations | orgFilter:listFilter.value">
            <td>{{ organization.organizationName }}</td>
            <td>{{ organization.city }}</td>
            <td>{{ organization.state }}</td>
            <td>{{ organization.country }}</td>
            <td>
                <i class="material-icons">mode_edit</i>
            </td>
            <td>
                <i class="material-icons">delete</i>
            </td>
        </tr>
        <tr>
            <td>
                <div class="col-md-4"><input type="text" #listFilter (keyup)="0" /></div>
            </td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
</tbody>

i am getting an error browser_adapter.js:84 TypeError: Cannot read property 'toLowerCase' of undefined at t.transform (orgFilter.ts:9)

where is the problem? does this mean that args doesn't have any values? am i using pipe wrong in html?


Solution

  • Given the template you provided, it looks like instances of Organization have no member called "name", but a member called "organizationName" instead.

    Maybe you can try replacing

    org.name.toLowerCase().indexOf(filter) != -1
    

    with

    org.organizationName.toLowerCase().indexOf(filter) != -1
    

    in your code.

    UPDATE

    That said, you can try a different way of binding you filter expression:

    @Pipe({
      name: 'orgFilter'
    })
    export class OrgFilterPipe implements PipeTransform {
        transform(orgs: Organization[], expression:string): any {
           if(!expression){
                return orgs;
           }
           else {
                return orgs.filter((org:Organization) => org.organizationName.toLowerCase().indexOf(expression) != -1)
           }
    } 
    

    Where expression refers to a member of your component, let's say:

    filterExpression: string;
    

    Then change your input text to:

    <input type="text" [(ngModel)]="filterExpression">
    

    And change the pipe call to:

    <tr *ngFor="#organization of organizations | orgFilter:filterExpression">
    

    According to the documentation for a list filter you may have to declare your pipe as impure using:

    @Pipe({
      name: 'orgFilter',
      pure: false
    
    })