web-dev-qa-db-fra.com

Obtenir un tableau d'objets à partir d'un service Angular

Je suis nouveau sur Angular (et Javascript d'ailleurs). J'ai écrit un service Angular qui renvoie un tableau d'utilisateurs. Les données sont extraites de un appel HTTP qui renvoie les données au format JSON. Lors de la journalisation des données JSON renvoyées par l’appel HTTP, je constate que cet appel aboutit et que les données correctes sont renvoyées. J'ai un composant qui appelle le service pour obtenir les utilisateurs et une page HTML qui affiche les utilisateurs. Je ne parviens pas à transférer les données du service au composant. Je suppose que j'utilise mal l'Observable. J'utilise peut-être mal l'abonnement également. Si je commente l'appel de getUsers dans la fonction ngInit et décommentez l'appel getUsersMock, tout fonctionne correctement et les données affichées dans la zone de liste de la page HTML s'affichent.J'aimerais convertir les données JSON en un tableau ou en une liste d'utilisateurs du service, plutôt que de renvoyer JSON à partir du service. et que le composant le convertisse.

Données renvoyées par l'appel HTTP pour obtenir les utilisateurs:

[
    {
        "firstName": "Jane",
        "lastName": "Doe"
    },
    {
        "firstName": "John",
        "lastName": "Doe"
    }
]

user.ts

export class User {
    firstName: string;
    lastName: string;
}

user-service.ts

...
@Injectable
export class UserService {
    private USERS: User[] = [
        {
            firstName: 'Jane',
            lastName: 'Doe'
        },
        {
            firstName: 'John',
            lastName: 'Doe'
        }
    ];

    constructor (private http: Http) {}

    getUsersMock(): User[] {
        return this.USERS;
    }

    getUsers(): Observable<User[]> {
        return Observable.create(observer => {
            this.http.get('http://users.org').map(response => response.json();
        })
    }
...

user.component.ts

...
export class UserComponent implements OnInit {
    users: User[] = {};

    constructor(private userService: UserService) {}

    ngOnInit(): void {
        this.getUsers();
        //this.getUsersMock();
    }

    getUsers(): void {
        var userObservable = this.userService.getUsers();
        this.userObservable.subscribe(users => { this.users = users });
    }

    getUsersMock(): void {
        this.users = this.userService.getUsersMock();
    }
}
...

user.component.html

...
<select disabled="disabled" name="Users" size="20">
    <option *ngFor="let user of users">
        {{user.firstName}}, {{user.lastName}}
    </option>
</select>
...

!!! MISE À JOUR !!!

J'avais lu le tutoriel "Heroes", mais je ne travaillais pas pour moi, alors je suis parti et j'ai essayé d'autres choses. J'ai ré-implémenté mon code comme décrit dans le didacticiel des héros. Cependant, lorsque je me connecte à la valeur de this.users, il indique non défini.

Voici mon user-service.ts révisé

...
@Injectable
export class UserService {
    private USERS: User[] = [
        {
            firstName: 'Jane',
            lastName: 'Doe'
        },
        {
            firstName: 'John',
            lastName: 'Doe'
        }
    ];

    constructor (private http: Http) {}

    getUsersMock(): User[] {
        return this.USERS;
    }

    getUsers(): Promise<User[]> {
        return this.http.get('http://users.org')
            .toPromise()
            .then(response => response.json().data as User[])
            .catch(this.handleError);
    }
...

Voici mon user.component.ts révisé

...
export class UserComponent implements OnInit {
    users: User[] = {};

    constructor(private userService: UserService) {}

    ngOnInit(): void {
        this.getUsers();
        //this.getUsersMock();
    }

    getUsers(): void {
        this.userService.getUsers()
            .then(users => this.users = users);

        console.log('this.users=' + this.users); // logs undefined
    }

    getUsersMock(): void {
        this.users = this.userService.getUsersMock();
    }
}
...

!!!!!!!!!! SOLUTION DE TRAVAIL FINALE !!!!!!!!!! Ce sont tous les fichiers de la solution de travail finale:

user.ts

export class User {
    public firstName: string;
}

user.service.ts

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

import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';

import { User } from './user';

@Injectable()
export class UserService {
    // Returns this JSON data:
    // [{"firstName":"Jane"},{"firstName":"John"}]
    private URL = 'http://users.org';

    constructor (private http: Http) {}

    getUsers(): Observable<User[]> {
        return this.http.get(this.URL)
            .map((response:Response) => response.json())
                .catch((error:any) => Observable.throw(error.json().error || 'Server error'));
    }
}

user.component.ts

import { Component, OnInit }   from '@angular/core';
import { Router }              from '@angular/router';

import { User }        from './user';
import { UserService } from './user.service';


@Component({
    moduleId: module.id,
    selector: 'users-list',
    template:  `
        <select size="5">
            <option *ngFor="let user of users">{{user.firstName}}</option>
        </select>
    `
})

export class UserComponent implements OnInit{
    users: User[];
    title = 'List Users';

    constructor(private userService: UserService) {}

    getUsers(): void {
        this.userService.getUsers()
            .subscribe(
                users => {
                    this.users = users;
                    console.log('this.users=' + this.users);
                    console.log('this.users.length=' + this.users.length);
                    console.log('this.users[0].firstName=' + this.users[0].firstName);
                }, //Bind to view
                            err => {
                        // Log errors if any
                        console.log(err);
                    })
    }

    ngOnInit(): void {
        this.getUsers();
    }
}
18
Nho Jotom

Regardez votre code:

 getUsers(): Observable<User[]> {
        return Observable.create(observer => {
            this.http.get('http://users.org').map(response => response.json();
        })
    }

et le code de https://angular.io/docs/ts/latest/tutorial/toh-pt6.html (BTW. vraiment bon tutoriel, vous devriez le vérifier)

 getHeroes(): Promise<Hero[]> {
    return this.http.get(this.heroesUrl)
               .toPromise()
               .then(response => response.json().data as Hero[])
               .catch(this.handleError);
  }

Le HttpService dans Angular2 renvoie déjà un observable, vous n'avez donc pas besoin d'envelopper un autre Observable comme vous l'avez fait ici:

   return Observable.create(observer => {
        this.http.get('http://users.org').map(response => response.json()

Essayez de suivre le guide en lien que j'ai fourni. Vous devriez aller bien quand vous l'étudiez attentivement.

---MODIFIER----

Tout d’abord, OU vous enregistrez la variable this.users? JavaScript ne fonctionne pas de cette façon. Votre variable est indéfinie et c'est bien, en raison de l'ordre d'exécution du code!

Essayez de le faire comme ça:

  getUsers(): void {
        this.userService.getUsers()
            .then(users => {
               this.users = users
               console.log('this.users=' + this.users);
            });


    }

Voir où se trouve le fichier console.log (...)!

Essayez de démissionner de toPromise (), cela semble être juste pour ppl sans arrière-plan RxJs.

Attrapez un autre lien: https://scotch.io/tutorials/angular-2-http-requests-with-observables Créez à nouveau votre service avec les observables de RxJ.

8
jmachnik