1

I am new to Angular. I have an issue in dependency injection when displaying a list of contacts. I have a typescript interface array in which i am passing a static array of contacts which am trying to display in html.

my service class

 export class ContactService {

      contacts = {
        'contactsList': [
            {'id': 1, 'name': 'Rajesh', 'city': 'bangalore'},
            {'id': 2, 'name': 'Aarjith', 'city': 'london'},
            {'id': 3, 'name': 'Anjan', 'city': 'california'},
            {'id': 4, 'name': 'David', 'city': 'delhi'}
        ]
      };
      constructor(
      ) { }

      getContacts(): Observable<Contacts> {
        // send contacts to subscriber
        //return of({} as Contacts);
         return of(this.contacts);
      }
    }

model class

 export interface Contacts {
      contactsList: Contact[];
 }

 export interface Contact {
      id: number;
      name: string;
      city: string;
 }

My ContactListComponent

export class ContactListComponent implements OnInit {

      contacts:Contacts[]=[];//i am getting error in this line
      constructor(
        private contactService: ContactService
      ) { }

      ngOnInit() {
        // get contacts from service and assign it to contacts
        this.contactService.getContacts().subscribe((data) => {
            this.contacts = data;//error at this line
          });
      }

html for displaying

    <p class="title"> Contact Applications </p>
    <div class="list">
      <p *ngFor="let contact of contacts">
        {{contact.name}}
      </p>
    </div>

i am getting the error at the initialization Type 'Contacts' is missing the following properties from type 'any[]': length, pop, push, concat, and 26 more. where i am missing . i have changed the initialization to Contacts=[] but not seems to be working.

4
  • getContacts() returns an Observable<Contacts>. Not an Observable<Contacts[]>. So every event it emits is a single instance of Contacts. Not an array of Contacts. So assigning the Contacts emitted to contacts, wich is of type Contacts[], can't compile. Commented Jul 14, 2019 at 10:11
  • But changing the return type as Observable<Contacts[]> results in another error Type 'Observable<{ 'contactsList': { 'id': number; 'name': string; 'city': string; }[]; }>' is not assignable to type 'Observable'. Type '{ 'contactsList': { 'id': number; 'name': string; 'city': string; }[]; }' is missing the following properties from type 'Contacts[]': length, pop, push, concat, and 26 more. Do i need to change anything while subscribing too? Commented Jul 14, 2019 at 10:27
  • You must declare contacts:Contacts; instead of contacts:Contacts[]=[] on ContactListComponent Commented Jul 14, 2019 at 10:30
  • i tried declaring that way too but i am getting error in the subscribe Property 'contactsList' is missing in type 'Contacts[]' but required in type 'Contacts'. Commented Jul 14, 2019 at 10:35

3 Answers 3

3

There are a few mistakes in your code. It should be like this:

export interface Contacts {
  contactsList: Contact[];
}

export interface Contact {
  id: number;
  name: string;
  city: string;
}

@Injectable({providedIn: 'root'})
export class ContactService {
  contacts = {
    'contactsList': [
      { 'id': 1, 'name': 'Rajesh', 'city': 'bangalore' },
      { 'id': 2, 'name': 'Aarjith', 'city': 'london' },
      { 'id': 3, 'name': 'Anjan', 'city': 'california' },
      { 'id': 4, 'name': 'David', 'city': 'delhi' }
    ]
  };

  getContacts(): Observable<Contacts> {
    return of(this.contacts);
  }
}


export class ContactListComponent implements OnInit {
  contacts: Contact[]; // <= This is the correct type
  constructor(private contactService: ContactService) {}

  ngOnInit() {
    this.contactService.getContacts().subscribe((data: Contacts) => {
      // You need to get the contatactsList from the service answer.
      this.contacts = data ? data.contactsList : [];
    });
  }
}

See this demo.

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

3 Comments

Thanks. This code works and displaying result But its failing in the test file which i cannot modify.it('should get data from service', fakeAsync(() => { tick(100); // wait for observables to get flushed with data expect(component.contacts).toBe(testContatcts.contactsList); })); Argument of type 'Contact[]' is not assignable to parameter of type 'Expected'. Type 'Contact[]' is missing the following properties from type 'ObjectContaining': jasmineMatches, jasmineToString
Just import the json file (ex.: import data from '../assets/data.json';. I modified the demo to show you.
Yes . I tried that way for json data too. Thanks for your support.
1

Can you try this code :

export interface Contact {
  id: number;
  name: string;
  city: string;
}

export class ContactService {

  constructor() { }

  contacts: Contact[] = [
    { 'id': 1, 'name': 'Rajesh', 'city': 'bangalore' },
    { 'id': 2, 'name': 'Aarjith', 'city': 'london' },
    { 'id': 3, 'name': 'Anjan', 'city': 'california' },
    { 'id': 4, 'name': 'David', 'city': 'delhi' }
  ];

  getContacts(): Observable<Contact[]> {
    return of(this.contacts);
  }
}

export class ContactListComponent implements OnInit {

  constructor(
    private contactService: ContactService
  ) { }

  contacts: Contact[] = [];

  ngOnInit() {
    this.contactService.getContacts().subscribe((contacts) => {
      this.contacts = <Contact[]>contacts;
    });
  }
}

1 Comment

Actually i tried this way which will not give compilation error but i cant change my interface in which we are having standalone test cases to pass it. So anything i can modify in list or service class to make it work?
0

You haven't defined an "Array Interface" with

export interface Contacts {
  contactsList: Contact[];
}

You've rather defined a type with an array typed property. The expression [] produces an Array value.

Therefore, the statement

let contacts: Contacts = [];

is malformed since an array doesn't have a contactList property.

The correct code would read

let contacts: Contacts = {
  contactList: []
};

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.