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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With