1

I have an interface

export interface IFilterable{
passesFilter(f : string, isFilter: boolean): boolean;
}

That I want to use to filter things in Angular2 pipe. It's implemented like this:

import {IFilterable} from './i-filterable';
import {Contains} from '../helpers/pipe-helpers';

export class Server extends Dto implements IFilterable {
name: string;
hostname: string;
ips: string;
operatingSystem: string;
sitesCount: number;
databasesCount: number;

passesFilter(f: string, isFilter: boolean): boolean {
    console.log('in server');
    if (!f || f === '') return isFilter;
    f = f.toLowerCase();

    return Contains(this.name, f) ||
        Contains(this.hostname, f) ||
        Contains(this.ips, f) ||
        Contains(this.operatingSystem, f);
}
}

Contains function being imported.

The pipe looks like this

import { Pipe, PipeTransform } from '@angular/core';
import {Contains} from '../helpers/pipe-helpers';
import {IFilterable} from '../models/i-filterable';

@Pipe({ name: 'serverFilter' })
export class ServerFilterPipe implements PipeTransform {
  transform(values: IFilterable[], search: string, isFilter: boolean):      IFilterable[] {
     console.log(search + ' search' + isFilter + values);
    return values.filter(value => {
    console.log(value.passesFilter);
    return value.passesFilter(search, isFilter)
  });
 }
}

The second console.log in the pipe prints undefined, and the one in passesFilter never even gets called. I also get en error

TypeError: setting a property that has only a getter

Am I doing something wrong, or are interfaces not really usable like that in TS?

Edit: Implementing same thing with an abstract class.

export abstract class Dto {
abstract passesFilter(f: string, isFilter: boolean): boolean;
}

Server

import {Dto} from './dto';
import {Contains} from '../helpers/pipe-helpers';

export class Server extends Dto {
name: string;
hostname: string;
ips: string;
operatingSystem: string;
sitesCount: number;
databasesCount: number;

passesFilter(f: string, isFilter: boolean): boolean {
    console.log('in server');
    if (!f || f === '') return isFilter;
    f = f.toLowerCase();

    return Contains(this.name, f) ||
        Contains(this.hostname, f) ||
        Contains(this.ips, f) ||
        Contains(this.operatingSystem, f);
}
}

pipe

import { Pipe, PipeTransform } from '@angular/core';
import {Dto} from '../models/dto';

@Pipe({ name: 'serverFilter' })
export class ServerFilterPipe implements PipeTransform {
transform(values: Dto[], search: string, isFilter: boolean): Dto[] {
console.log(search + ' search' + isFilter + values);
return values.filter(value => {
  console.log(value.passesFilter);
  return value.passesFilter(search, isFilter)
});
 }
}

pipe-helpers

export function Contains(val: string, cmp: string) {
    return val ? val.toLowerCase().indexOf(cmp) >= 0 : false;
}
1
  • Could you please create a plunkr? Commented Sep 13, 2016 at 19:24

1 Answer 1

1

We don't see the input of your pipe.. maybe that values aren't from type IFilterable ?! anyway i would check values before using it.. maybe its undefined during first pipe round..

@Pipe({ name: 'serverFilter' })
export class ServerFilterPipe implements PipeTransform {
   transform(values: IFilterable[], search: string, isFilter: boolean): IFilterable[] {
      console.log(search + ' search' + isFilter + values);
      if (!values || !values.length) return []; // check that input !

      return values.filter(value => {
         if (!value || !value.passesFilter) return false; // check that value !

         console.log(value.passesFilter);
         return value.passesFilter(search, isFilter)
      });
   }
}

And a hint for you:

if (!f || f === '') return isFilter;

this check is redundant.. !'' is true.

UPDATE

Check this plunker: https://plnkr.co/edit/IhM4rKqD3VvEZVBdimzK?p=preview

Sign up to request clarification or add additional context in comments.

12 Comments

Hey, sorry for responding so late. I updated TS to version 2 and Angular to release version as well. I tried doing it again with an interface and an abstract class and got the same result. All the values print fine that you said to check. And the array is of type Server and server implements IFilterable. I get the array from a service that returns an observable of Server[]. Code suggestion even lets me select the passesFilter method. But when I run it I get an error in the console that value.passesFilter is not a function.
It doesn't work even if I inherit the method from a superclass, that is not abstract.
please do this in your pipe: console.dir(values); to see that incoming array and verify whats in that array..
see my edit.. added a demo plunker. :) hope it helps.
does your service create that Server[] with new Server() or comes it from a JSON format? in this case there will be of course no functions inside..
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.