[Ionic 3] Empty List with *ngFor and pipe (present data from object) [Solved]

Hello,

I am trying to list with *ngFor and a pipe data from an object but it’s not working.

I am trying to do this:

but i am presented with:

Can anyone help me, please?

Thanks!

Template - home.html

<ion-header>
  <ion-navbar>
    <ion-title text-center>
      Contactos
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content>

<ion-list>
  
  <button ion-item *ngFor="let theUser of myUser | keys">
    
    <ion-avatar item-start>
      <img src="{{theUser?.picture}}"/>
    </ion-avatar>
    
    <h2>{{theUser?.login}}</h2>
    
    <p>{{theUser?.name}}</p>
    
  </button>
  
</ion-list>

</ion-content>

Module - home.ts

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { Http } from '@angular/http';
import { Observable } from 'rxjs';
import { ContactosApiProvider, User } from '../../providers/contactos-api/contactos-api';
import 'rxjs/add/operator/map';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
  name: Observable<any>;
  myUser: User;

  constructor(public navCtrl: NavController, public contactosApiProvider: ContactosApiProvider) {
      contactosApiProvider.getData().subscribe(newUser => {
        this.myUser = newUser;
      });
    }
}

Pipe - keys.ts

import { Pipe, PipeTransform } from '@angular/core';
 
@Pipe({
	name: 'keys',
})
export class KeysPipe implements PipeTransform {
 
	transform(value: any, args?: any[]): any[] {
 
		if(value) {
 
			let keyArr: any[] = Object.keys(value),
			dataArr = [];
 
			keyArr.forEach((key: any) => {
				dataArr.push(key);
			});
 
			return dataArr;
		}
	}
}


Provider - contactos-api.ts

import { Http, Response } from "@angular/http";
import { Injectable } from '@angular/core';
import 'rxjs/add/operator/map';
import { Observable } from "rxjs";

export class User{
  name: String;
  location: String;
  email: String;
  login: String;
  dob: String;
  registered: String;
  phone: String;
  cell: String;
  picture: String;
  nat: String;
  
  constructor(name, location, email, login, dob, registered, phone, cell, picture, nat){
    this.name = name;
    this.location = location;
    this.email = email;
    this.login = login;
    this.dob = dob;
    this.registered = registered;
    this.phone = phone;
    this.cell = cell;
    this.picture = picture;
    this.nat = nat;
  }
  
}


@Injectable()
export class ContactosApiProvider {

  constructor(private http: Http) {
  }

  getData(){
    return this.http.get('https://randomuser.me/api')
    .map((data: Response) => data.json())
    .map(res => {
      return new User(res['results'][0].name.first, 
      res['results'][0].location.street, 
      res['results'][0].email, 
      res['results'][0].login.username, 
      res['results'][0].dob, 
      res['results'][0].registered, 
      res['results'][0].phone, 
      res['results'][0].cell, 
      res['results'][0].picture.thumbnail, 
      res['results'][0].nat);
    });
  }

}


App - app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';
import { HttpModule } from '@angular/http';


import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { DetalhesPage } from '../pages/detalhes/detalhes';
import { ContactosApiProvider } from '../providers/contactos-api/contactos-api';
import { KeysPipe } from '../pipes/keys/keys';

@NgModule({
  declarations: [
    MyApp,
    HomePage,
    DetalhesPage,
    KeysPipe
  ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp),
    HttpModule
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage,
    DetalhesPage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    {provide: ErrorHandler, useClass: IonicErrorHandler},
    ContactosApiProvider
  ]
})
export class AppModule {}

Ionic Framework: 3.9.2
Ionic App Scripts: 3.1.0
Angular Core: 5.0.0
Angular Compiler CLI: 5.0.0
Node: 6.12.0

  1. Your version of Node has a security hole. Update to current LTS strongly recommended.
  2. Using ? in a template is almost always bad style, because it masks errors in Observable logic.
  3. You need to decide exactly how you want your Observables to interact with the template. I personally use the async pipe, and don’t use “subscribe” in my page controllers. Other posters handle this in other ways.
1 Like

@AaronSterling

  1. When i try to upgrade it gives the error: cp: not writing through dangling symlink ‘/usr/local/bin/node’ .
  2. With the following code (*ngFor and pipe removed) i have to put the ? to present data, if i remove ? it gives the error _co.myUser is undefined.

home.html

<ion-header>
  <ion-navbar>
    <ion-title text-center>
      Contactos
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content>

<ion-list>
  
  <button ion-item>
    
    <ion-avatar item-start>
      <img src="{{myUser?.picture}}"/>
    </ion-avatar>
    
    <h2>{{myUser?.login}}</h2>
    
    <p>{{myUser?.name}}</p>
    
  </button>
  
</ion-list>

</ion-content>
  1. I am still a newbie (doing the IonicAcademy.com course).

I’m having a really hard time understanding what you’re trying to do here.

Are you trying to display a list of contacts, or show the keys from a single user?

You say you want to do the former, but your code seems to be wanting to do both at best, which is why it’s not displaying anything.

@SigmundFroyd

I want to display a list of contacts. I was using the pipe (keys) because i thought that was necessary to parse the data from Json to Array to display it with *NgFor.

I will update in the post below all the code (same inicial error but i am trying this time to parse without the pipe).

«Error trying to diff ‘[object Object]’. Only arrays and iterables are allowed.»

Please, can anyone help me?
Thanks.

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';
import { HttpModule } from '@angular/http';


import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { DetalhesPage } from '../pages/detalhes/detalhes';
import { ContactosApiProvider } from '../providers/contactos-api/contactos-api';
import { KeysPipe } from '../pipes/keys/keys';

@NgModule({
  declarations: [
    MyApp,
    HomePage,
    DetalhesPage,
    KeysPipe
  ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp),
    HttpModule
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage,
    DetalhesPage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    {provide: ErrorHandler, useClass: IonicErrorHandler},
    ContactosApiProvider
  ]
})
export class AppModule {}

Provider: contactos-api.ts

import { Http, Response } from "@angular/http";
import { Injectable } from '@angular/core';
import 'rxjs/add/operator/map';
import { Observable } from "rxjs";

@Injectable()
export class ContactosApiProvider {

  constructor(private http: Http) {
  }

  getData(){
    return this.http.get('https://randomuser.me/api/?results=10')
    .map((data: Response) => data.json());
  }
}

home.ts

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { Http } from '@angular/http';
import { Observable } from 'rxjs';
import { ContactosApiProvider} from '../../providers/contactos-api/contactos-api';
import 'rxjs/add/operator/map';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
  myUser = [];

  constructor(public navCtrl: NavController, public contactosApiProvider: ContactosApiProvider) {
      contactosApiProvider.getData().subscribe(newUser => {
        this.myUser = newUser;
        console.log(this.myUser);
      });
   }
}

home.html

<ion-header>
  <ion-navbar>
    <ion-title text-center>
      Contactos
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content>

<ion-list>
  
  <button ion-item *ngFor="let theUser of myUser">
    <p>{{theUser.name.last}}</p>
  </button>

</ion-list>

</ion-content>

I solved the above error with:

this.myUser = newUser.results;

Results is the name of the called object api (ex. from https://randomuser.me/api/?results=10 ).

Provider - contactos-api.ts

import { Http, Response } from "@angular/http";
import { Injectable } from '@angular/core';
import 'rxjs/add/operator/map';
import { Observable } from "rxjs";

@Injectable()
export class ContactosApiProvider {

  constructor(private http: Http) {
  }

  getData(){
    return this.http.get('https://randomuser.me/api/?results=10')
    .map((data: Response) => data.json());
  }
  
}

home.ts

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { Http } from '@angular/http';
import { Observable } from 'rxjs';
import { ContactosApiProvider} from '../../providers/contactos-api/contactos-api';
import 'rxjs/add/operator/map';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
  myUser = [];

  constructor(public navCtrl: NavController, public contactosApiProvider: ContactosApiProvider) {
      contactosApiProvider.getData().subscribe(newUser => {
        this.myUser = newUser.results;
        console.log(this.myUser);
      });
   }
}

Hai marcooliva can you send me steps for your project it will be useful for me thankyou.

Hello @gomathyfn,

First i searched a free test API (https://randomuser.me/api/?results=10). Please, note that this API is enclapsulated in one array called “results”. There are other types of API without enclapsulation that requires another type of code. If that is your case, please tell me and i will try to help you.
Then i started creating the Provider - contactos-api.ts:

import { Http, Response } from "@angular/http";
import { Injectable } from '@angular/core';
import 'rxjs/add/operator/map';
import { Observable } from "rxjs";

@Injectable()
export class ContactosApiProvider {

  constructor(private http: Http) {
  }

  getData(){
    return this.http.get('https://randomuser.me/api/?results=10')
    .map((data: Response) => data.json());
  }
}

Do not forget to add in the app.module.ts the provider page name:

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';
import { HttpModule } from '@angular/http';


import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { DetalhesPage } from '../pages/detalhes/detalhes';
import { ContactosApiProvider } from '../providers/contactos-api/contactos-api';

@NgModule({
  declarations: [
    MyApp,
    HomePage,
    DetalhesPage
  ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp),
    HttpModule
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage,
    DetalhesPage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    {provide: ErrorHandler, useClass: IonicErrorHandler},
    ContactosApiProvider
  ]
})
export class AppModule {}

Then i created the module - home.ts:

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { Http } from '@angular/http';
import { Observable } from 'rxjs';
import { ContactosApiProvider} from '../../providers/contactos-api/contactos-api';
import 'rxjs/add/operator/map';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
  myUser = [];

  constructor(public navCtrl: NavController, public contactosApiProvider: ContactosApiProvider) {
      contactosApiProvider.getData().subscribe(newUser => {
        this.myUser = newUser.results;
        console.log(this.myUser);
      });
   }
}

And finally i created the template - home.html:

<ion-header>
  <ion-navbar>
    <ion-title text-center>
      Contactos
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content>

<ion-list>
  
  <button ion-item *ngFor="let theUser of myUser">
    <p>{{theUser.name.last}}</p>
  </button>

</ion-list>

</ion-content>

P.S.: I recommend also this free Ionic Framework course: https://ionicacademy.com/ionic-crash-course/?utm_source=devdacticheader

Best Regards,
Marco Oliva

Thank you so much @marcooliva