Soy nuevo en Angular 2, proveniente de un fondo Jquery. Estoy luchando con las cosas simples.

Mi primera tarea es completar una tabla HTML desde una API que me está sirviendo JSON.

El problema es incluso antes de intentar crear el html. Estoy tratando de llenar una matriz de objetos de clase de correo desde json, pero sigue volviendo indefinido. He registrado el violinista y se está sirviendo el json.

Yo he creado:

  • get-mail.service.ts para descargar el json
  • inbboxmail.component.html | ts | css para ser la vista
  • mail.ts para ser mi modelo

Get-mail.service.ts: aquí el registro de la consola de la función .map vuelve con todo el json (como esperaba) pero el registro de la consola .do no está definido

import { Injectable, Inject } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs';
import { Mail } from "../model/mail"   // My Model

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

@Injectable()
export class GetMailService {

    constructor(private http: Http, @Inject('ORIGIN_URL') private originUrl: string) {}

  getMail(): Observable<Mail[]> {
      return this.http.get(this.originUrl + '/api/mail/')
          // ...and calling .json() on the response to return data
          .map((res: Response) => { res.json(); console.log("map", res.json()); })  //This is coming back with my entire json
          .do(data => console.log("all:" + JSON.stringify(data))) //all: undefined
          //...errors if any
          .catch((error:any) => Observable.throw(error.json().error || 'Server error'));
  }

}

Inboxmail.component.ts // todos los registros de la consola vuelven indefinidos

import { Component, Inject } from '@angular/core';
import { GetMailService } from '../../../services/get-mail.service';
import { Observable } from 'rxjs';
import { Mail } from '../../../model/mail'

@Component({
    selector: 'inboxmail',
    templateUrl: './inboxmail.component.html',
    styleUrls: ['./inboxmail.component.css'],
    providers: [GetMailService]

})
export class InboxMailComponent {
    public mail: Mail[];

    constructor(private service: GetMailService) {
        service.getMail()
            .subscribe(_mail => { console.log("mail", _mail); this.mail = _mail },  
                 null,
                 () => console.log("complete", this.mail));
    }

}

Modelo de correo

export class Mail {
    constructor(
        public reference: string,
        public ocrText: string,
        public status: string,
        public create: Date
    ) { }
}

Json servido (acortado para fines de ejemplo)

[{"reference":"1897","ocrText":"magna adipiscing euismod euismod elit . ","status":"Stored","created":"2017-07-04T14:09:25.2565869Z"},{"reference":"1897","ocrText":"magna adipiscing euismod euismod elit . ","status":"Stored","created":"2017-07-04T14:09:25.2565869Z"}]
0
michael 24 jun. 2017 a las 17:26

3 respuestas

La mejor respuesta

Cambie el método de servicio a:

getMail(): Observable<Mail[]> {
    /*return this.http.request('./data/people.json')
        .map(res => res.json());*/
      return this.http.get(this.originUrl + '/api/mail/')
          // ...and calling .json() on the response to return data
          .map((res: Response) => { console.log("map", res.json());return res.json(); })  //This is coming back with my entire json
          .do(data => console.log("all:" + JSON.stringify(data))) //all: undefined
          //...errors if any
          .catch((error:any) => Observable.throw(error.json().error || 'Server error'));
  }

Y cambie la definición de su modelo de datos a una interfaz de la siguiente manera:

export interface Mail {
    reference: string;
    ocrText: string;
    status: string;
    create: Date;
}

¿Por qué una interfaz? Bueno, su servicio está devolviendo una cadena en formato JSON que se puede asignar a POJO cuyas propiedades se pueden definir mediante una interfaz. Si desea utilizar una clase, debe asignar cada POJO a una instancia de esa clase mediante el uso de correo nuevo (.....).

1
Jota.Toledo 24 jun. 2017 a las 14:32

Sugiero convertir el Observable en un Promise utilizando el operador toPromise, ya que Promise puede ser más fácil de entender que Observable.

import 'rxjs/add/operator/toPromise';
getHero(id: number): Promise<Hero> {
  const url = `${this.heroesUrl}/${id}`;
  return this.http.get(url)
    .toPromise()
    .then(response => response.json().data as Hero)
    .catch(this.handleError);
}

Vea el tutorial oficial aquí.

1
awmleer 24 jun. 2017 a las 14:32

Aquí está tu problema:

.map((res: Response) => { res.json(); console.log("map", res.json()); })

Cuando llamas a res.json(), devuelve el objeto JSON pero en realidad no lo reenvías al siguiente paso en tu transmisión (el do()). Cambia esa línea a

.map((res: Response) => res.json())

Ahora está devolviendo el objeto JSON, que estará disponible como entrada para su do() y se emitirá en su Subscription

1
BeetleJuice 24 jun. 2017 a las 14:35