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

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.