3

I've been sitting with a problem for the past days & I can't seem to get a solution anywhere. Background: I have a typescript class defined as follows:

export class Client extends Person {
    claimNumber: string;
    policyNumber: string;
    address: string;
    insuranceCompany: Organisation = new Organisation();

    toString(): string {
        return this.policyNumber
            .concat(this.claimNumber);
    }
}

The above is used as a model that drives an angular 5 template. In my component, I fetch (using angular 5 HttpClient) a list of clients from a remote api & generate an html table rows. The LOC to generate the table rows is:

<tr *ngFor="let client of clients | filter:searchString"> ... </tr>

searchString above is property bound to a search input tag & filter is a custom filter Pipe defined as follows:

export class FilterPipe implements PipeTransform {
    transform(items: Client[], term: string) {               
        if (term == undefined || term === '') return items;
        return items.filter(item =>item.toString().toLocaleLowerCase().includes(term.toLocaleLowerCase()));
    }
}

Problem: When I inspect item.toString() in the filter pipe above, it returns [object Object] as opposed to a string made up of policyNumber, & claimNumber.

Investigation: I investigated this issue as follows: I instantiated the Client class as follows:

let c = new Client();
c.policyNumber = 'ababababa';
c.claimNumber = 'aaaaaaa';
console.log('client toString() is => ' + c.toString());

Interesting enough, the console.log above outputs : 'ababababaaaaaaaa'.

Question: What am I doing wrong that results in the item.toString() in the filter pipe return [object Object] whereas toString() on a class I instantiated returns the correct string?

  • Instead of inspecting item.toString() within the filter, have you checked both policy and claimNumbers? How is the data coming from the API? How does it looks like? – Luis Deras Apr 19 '18 at 18:04
  • Possible duplicate of [HttpClient not running constructor](https://stackoverflow.com/questions/46570775/httpclient-not-running-constructor) – ConnorsFan Apr 19 '18 at 18:04
  • 1
    I think that the solution to your problem is in [this answer](https://stackoverflow.com/a/46570840/1009922). – ConnorsFan Apr 19 '18 at 18:06
  • thank you very much for sharing the links, they greatly contributed to finding a solution to my problem. – Mokau Masemola Apr 21 '18 at 18:32

2 Answers2

3

If you get the clients from a WebService (or something similar), you are just getting plain json objects. If you say that the received objects are of type Client, typescript will show them as objects of such type, but only the properties will be the same, the methods will not be from the Client class, but from the Object class.

You might want to instantiate them as real client objects after you retrieve them from the server:

public myServiceMethod() {
    return this.http.get(...).map(plainClients => {
        const realClients: Array<Client> = (plainClients || []).map(plainClient => {
            let realClient = new Client();
            realClient.claimNumber = plainClient.claimNumber;
            realClient.policyNumber = plainClient.policyNumber;
            realClient.address = plainClient.address;
            return realClient;
        });
        return realClients;
    })
}

You might prefer to use anemic objects with their types being interfaces, and use an utilitarian function to retrieve the client as a string, to avoid cases like the one you're having:

export interface Person {
    ...
}

export interface Client extends Person {
    claimNumber: string;
    policyNumber: string;
    address: string;
    insuranceCompany: Organisation;
}

// In some utilitarian class
public static getClientInfo(client: Client) {
    return client.policyNumber.concat(client.claimNumber);
}

// In your pipe
return items.filter(item => getClientInfo(item).toLocaleLowerCase().includes(term.toLocaleLowerCase()));

I'm not saying to just use anemic classes in your app, but if some type of object is passed around and will probably be serialized, then using anemic objects can avoid problems like the one you are having.

Lucas Basquerotto
  • 7,260
  • 2
  • 47
  • 61
  • 1
    Yeah, I was assuming he was instantiating each client into an instance of the Client class. Typescript definitely doesn't do that for you. – frodo2975 Apr 19 '18 at 18:42
  • Thank you very much, this helped a lot in understanding the underlying issue & helped in devising a solution to the problem. Much gratitude & may you receive all the blessings. – Mokau Masemola Apr 21 '18 at 18:31
0

A way to figure out what the problem might be would be to rename your method to something that isn't a built in method name, like maybe toSearchString. It would also be worth adding console logs to your filter function to make sure you're actually getting clients there. You may actually be getting a different object.

frodo2975
  • 10,340
  • 3
  • 34
  • 41