0

I have the following class in an Angular2 app

export class Contact { constructor( public has_reply: boolean, public archived: boolean ) { } getStatus() : string { if (this.archived) { return "Archived"; } if (this.has_reply) { return "Answered"; } return "Waiting"; } } 

which is returned by a service

@Injectable() export class ContactsService { private contactsData : BehaviorSubject<Array<Contact>> = null; constructor(private http: Http) { this.contactsData = new BehaviorSubject<Array<Contact>>([]); } /** * get the list of contacts */ populateContacts() : Array<Contact> { return this.http.get('/api/contacts/').map( (res: Response) => {return res.json()} ).subscribe( jsonData => { this.contactsData.next(<Array<Contact>> jsonData); } ); } onContactsChanged() : Observable<Array<Contact>>{ return this.contactsData.asObservable(); } } 

which is used in a component

@Component({ selector: 'app-home', templateUrl: './home.component.html', styleUrls: ['./home.component.css'] }) export class HomeComponent implements OnInit { private contacts: Array<Contact> = []; constructor( private contactsApi : ContactsService ) { } ngOnInit() { this.contactsApi.onContactsChanged().subscribe( (contacts: Array<Contact>) => {this.contacts = contacts;} ); this.contactsApi.populateContacts(); } } 

and displayed in a template

<table class="table table-striped table-bordered"> <tr *ngFor="let contact of contacts"> <td> {{ contact.getStatus() }} </td> </tr> 

I get the following error

EXCEPTION: Error in ./HomeComponent class HomeComponent - inline template:11:8 caused by: self.context.$implicit.getStatus is not a function 

What is wrong in my approach? Does Angular2 allow to call a class method like this?

Note : Calling method from a Angular 2 class inside template looks similar question but it did not help

2
  • 1
    From what I've seen, this is usually an issue with type casting. Please take a look at this question. Commented Nov 16, 2016 at 10:35
  • @AdnanA. : Yes! that's a casting issue and your link is really helpful. Feel free to change your comment into answer and I will accept it. Commented Nov 16, 2016 at 10:48

2 Answers 2

1

As suggested by @AdnanA, the problem is a casting issue. See How to do runtime type casting in TypeScript?

I fixed by casting each object of the array: See https://stackoverflow.com/a/32186367/117092

// Thank you! https://stackoverflow.com/a/32186367/117092 function cast<T>(obj, cl): T { obj.__proto__ = cl.prototype; return obj; } @Injectable() export class ContactsService { private contactsData : BehaviorSubject<Array<Contact>> = null; constructor(private http: Http) { this.contactsData = new BehaviorSubject<Array<Contact>>([]); } /** * get the list of contacts */ populateContacts() : Array<Contact> { return this.http.get('/api/contacts/').map( (res: Response) => {return res.json()} ).subscribe( jsonData => { // WRONG! this.contactsData.next(<Array<Contact>> jsonData); // FIXED BY let contactsArray: Array<Contact> = []; for (let i=0, l=jsonData.length; i<l; i++) { let contact = cast<Contact>(jsonData[i], Contact); contactsArray.push(contact); } this.contactsData.next(contactsArray); } ); } onContactsChanged() : Observable<Array<Contact>>{ return this.contactsData.asObservable(); } } 
Sign up to request clarification or add additional context in comments.

Comments

0

If the data is acquired async you need to guard against null

{{ contact?.getStatus() }} 

2 Comments

I don't think this is a type. I want to call the getStatus of the contact object. contacts is the list
I see. I missed that when I searched for contact. I updated my answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.