0

I'm doing the request and it returns me an Observable correctly, however I want to get these returned objects to be of type Setor, I'm doing a generic method in my ServiceBase passing the type of object to be returned via Generics.

Setor class:

import { UUID } from 'angular2-uuid'

export class Setor {
    descricao: string;
    id: UUID;
}

setor.component.ts:

import { element } from 'protractor';
import { Component, OnInit } from '@angular/core';

import { SetorService } from './service/setor.service';
import { Setor } from "app/retaguarda/setor/model/setor";

@Component({
  selector: 'app-setor',
  templateUrl: './setor.component.html',
  styleUrls: ['./setor.component.css']
})

export class SetorComponent implements OnInit {

  setor: Setor;

  private setores: Setor[]; // Lista de setores

  constructor(public setorService: SetorService) {
  }

  ngOnInit() {
    this.setor = new Setor();
  }

  obterTodos(form) {
    let t = this.setorService.obterSetores().subscribe(setores => this.setores = setores);
      console.log(t);
  }
}

setor.service.ts:

import { Observable } from 'rxjs/Observable';
import { BaseService } from './../../../shared/service/base/base.service';
import { Injectable } from '@angular/core';
import { Setor } from "app/retaguarda/setor/model/setor";
import { Http } from "@angular/http";

@Injectable()
export class SetorService extends BaseService {

  uriApi: string = 'setor';

  constructor(httpService: Http) {
    super(httpService);
  }

  obterSetores(): Observable<Setor[]> {
    return this.obterTodos<Setor>('setor');
  }
}

base.service.ts:

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

// Observable class extensions
import 'rxjs/add/observable/of';
import 'rxjs/add/observable/throw';
import 'rxjs'

// Observable operators
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/switchMap';

@Injectable()
export class BaseService {

  serviceUrl: string = 'http://localhost:5780/api/';
  headers: Headers;
  options: RequestOptions

  constructor(private httpService: Http) {
    this.headers = new Headers({
      'Content-Type': 'application/json',
      'Accept': 'q=0.8;application/json;q=0.9'
    });
    this.options = new RequestOptions({ headers: this.headers });
  }

  private getAll<T>(url: string): Observable<T[]> {
    return this.httpService
      .get(url)
      .map(res => res.json() as T[])
      .catch(this.handleError);
  }

  protected obterTodos<T>(url: string): Observable<T[]> {
    return this.getAll(this.serviceUrl + url);
  }

  private post<T>(url: string, data: T): Observable<T> {
    let jsonContent = JSON.stringify(data);
    return this.httpService
      .post(url, jsonContent, this.options)
      .map(this.extractData)
      .catch(this.handleError);
  }

  private extractData<T>(res: Response) {
    let body = res.json() as any;
    return body || {};
  }

  private handleError(error: any) {
    let errMsg = (error.message) ? error.message :
      error.status ? `${error.status} - ${error.statusText}` : 'Server error';
    console.error(errMsg);
    return Observable.throw(errMsg);
  }
}

JSON returned:

    [
        {
        "Descricao": "teste 1",
        "Id": "4b78ade1-39a1-11e7-a8f1-a41f72fdda5d"
        },
        {
        "Descricao": "teste 2",
        "Id": "4b7cb16f-39a1-11e7-a8f1-a41f72fdda5d"
        },
        {
        "Descricao": "teste 3",
        "Id": "4b807449-39a1-11e7-a8f1-a41f72fdda5d"
        }
   ]

What is missing so that the return in JSON is deserializable for the Setor class?

12
  • What is the problem? Commented May 16, 2017 at 13:50
  • @echonax The answer is an array of objects. I need the return to be an array of Setor Commented May 16, 2017 at 13:51
  • Do you mean your console.log(t); gives you not what you want? Commented May 16, 2017 at 13:52
  • @echonax T is the array of objects, it should be the array of Sectors. This is the precise problem of a strongly typed return. Commented May 16, 2017 at 13:53
  • Why not just use interfaces, or is there a special reason for use of class? If so, you'd have to first of all modify the class and add a constructor in it. Commented May 16, 2017 at 13:56

1 Answer 1

1

If you want to use Classes ... First you need to add a constructor to your class in this case, so that we can map to new objects of type Setor.

export class Setor {
  constructor(
    public descricao: string;
    public id: UUID;
  ) {}
}

Then we have to map each Setor from your response since the properties do not match, otherwise we could use Object.assign without explicitly stating properties.

obterSetores(): Observable<Setor[]> {
  return this.obterTodos<Setor>()
    .map(res => res.map(x => new Setor(x.Descricao, x.Id)))
}

That should pretty much do it :)

DEMO

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

2 Comments

worked perfectly!!!!!! But the properties are empty, just need to correct this and everything is right!
Great, glad to hear! If the properties are empty, there might be some issue with the properties being different still? Since the plunker works fine with the code provided. You just need to check those properties closely, hope you can figure it out. If not, fork the plunker where you recreate the issue and just holler and I can take a look :)

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.