4

I'm following a simple guide and amending it lightly for my needs - But I have finally hit a snag regarding mapping and subscribing

https://www.sitepoint.com/mean-stack-angular-2-angular-cli/ - This is the guide and everything is working until I go to build the app after building out the List Service.

I've made a few amendments due to Angular 5 such as replacing with HttpClient, but nothing out of the ordinary.

My present issue falls on these 2 functions:

  public getAllTasks():Observable<Task[]> {
    let URI = `${this.serverApi}/tasks/`;
    return this.http.get(URI)
      .map(res => res.json())
      .map(res => <Task[]>res.tasks);
  }



  public deleteTask(taskId : string){
    let URI = `${this.serverApi}/tasks/${taskId}`;
    let headers = new HttpHeaders;
    headers.append('Content-Type', 'application/json');
    return this.http.delete(URI,  {headers})
      .map(res => res.json());

  }

Even my IDE tells me that

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

won't work in either function, saying: Property 'json' does not exist on type 'Object'.

I've searched around a bit and found some older post with suggestions such as modifying it to be

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

but that gave me a very similar error

A function whose declared type is neither 'void' nor 'any' must return a value.

My model is:

export interface Task {
  _id?: string;
  title: string;
  description: string;
  category: string;
}

Originally this was a class, but I modified it to an interface, as was recommended. I'm unsure if it is related.

Unsure if it's relative, but the component side of it is:

 ngOnInit() {
    this.loadTasks();
  }

  public loadTasks() {

    this.taskServ.getAllTasks().subscribe(
      response => this.tasks = response,
    )
  }

I assume this is some confusion I have with how map works or what it expects. Any input would be appreciated.

Update

Angular - res.json() is not a function

As mentioned in this post, it seems that HttpClient natively returns the res in JSON, so actually deleting those lines removed the errors. I will post my complete solution once I have it proved out.

DNorthrup
  • 827
  • 2
  • 8
  • 26
  • 1
    Possible duplicate of [Property 'json' does not exist on type 'Object'](https://stackoverflow.com/questions/46005430/property-json-does-not-exist-on-type-object) – Kaibo Nov 01 '19 at 12:57

5 Answers5

11

With HttpClient, you don't need map(res => res.json()) You can get the data from the json as follow:

    public getAllTasks():Observable<Task[]> {
        let URI = `${this.serverApi}/tasks/`;
        return this.http.get<Task[]>(URI);
    }

See https://angular.io/guide/http

And in your component, from which you are calling your service you can subscribe to the asynchronous data:

 export class TestComponent implements OnInit {
    tasks: Task[];

    constructor(private taskService: MyTaskService) {
    }

    ngOnInit(): void {
     this.taskService.getAllTasks().subscribe((data: Task[]) => {
          this.tasks = data;
        });
    }

    //other methods

    }

In the HTML, where you are listing the tasks, you should use optional chaining operator {{ tasks?.length }}, in order to avoid possible errors in the browser's console.

Chau Tran
  • 4,668
  • 1
  • 21
  • 39
  • How do I get it to return as an array? Is it JS Manipulation, or is there a proper map/subscribe method I'm missing? (It's presently kicking an error due to only one object - No array) – DNorthrup Nov 30 '17 at 02:28
  • How do you get the response as of the moment? Object? Can I see your log? Or better yet, is this a public project that you can share? I'd love to clone and take a closer look. I'm really not good at looking at codes and give answer :) – Chau Tran Nov 30 '17 at 03:16
  • I use HttpClient but I get the error that ` Property 'auth_token' does not exist on type 'Object'.` when using it as `.map(res => { // login successful if there's a jwt token in the response if (!res.auth_token) return;` – Rafael Jul 06 '18 at 08:37
4

Use this code sample .map((res: Response) => res.json()) as .map(res => res.json())

alexander.polomodov
  • 5,396
  • 14
  • 39
  • 46
1

My answer lied in mapping the response a bit differently.

  public getAllTasks():Observable<Task[]> {
    let URI = `${this.serverApi}/tasks/`;
    return this.http.get<{tasks: Task[]}>(URI)
      .map(res => res.tasks)
  }

By mapping it as the HTTPClient standard, it resolved my issue of being returned object Object to the component.

My component remained unchangeds

  public loadTasks() {

    this.taskServ.getAllTasks().subscribe(
      response => this.tasks = response,
    );

  }
DNorthrup
  • 827
  • 2
  • 8
  • 26
0

With HttpClient you can directly do it as follows,

  public getAllTasks(): Observable<Task[]> {
    const URI = this.serverApi + '/api/task/';
    console.log(`Fetching all tasks from ${URI}...`);
    return this.http.get(URI).map(res => res.tasks)           
   }

and then in component,

loadTasks() {
    this.taskServ.getAllTasks().subscribe(taskList => {
      this.tasks = taskList;         
    });
  }
Sajeetharan
  • 216,225
  • 63
  • 350
  • 396
  • I tried this and I'm actually still getting the same error on `const tasks` line - 'json does not exist on type Object' – DNorthrup Nov 30 '17 at 02:13
  • @Sajeetharan it would gives error that tasks don't exist on type 'Object'. – Jun Feb 17 '18 at 22:29
0

Make sure you are using angular 4.3 and upper.

If you are using angular 4.3 and upper,you have to use

import { HttpClient } from '@angular/common/http';

in this case you do not have to use .map(res => res.json()) because angular new http automatic conversion from JSON to an object.

If you are using angular 4.3 lower ,you have to use

import { Http } from '@angular/http';

in these case use .map(res: Response => res.json())

Chamith
  • 69
  • 10