0

Im trying to set response array to an interface I have created (ApiPosts[]) And I'm getting this strange error when in trying to update the posts var to the response array. TypeError: undefined is not an object (evaluating 'this.posts = resText')

Now the response is an array of JSON objects. And when I console.log(res) i get an expected array of objects The code is as follows:

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { post } from 'selenium-webdriver/http';
import { Injectable } from '@angular/core';
import { map, filter, catchError, mergeMap } from 'rxjs/operators';


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

export class MyLikesComponent implements OnInit {

  posts:ApiPosts[];


  constructor(private http:HttpClient) { }

  ngOnInit() {

    var data = null;

    var xhr = new XMLHttpRequest();
    xhr.withCredentials = false;

    xhr.addEventListener("readystatechange", function () {
      if (this.readyState === 4) {
        var res = JSON.parse(this.responseText);
        console.log(res);
        setRes(res);
      }
    });

    xhr.open("GET", my url);
    xhr.setRequestHeader("content-type", "application/json");
    xhr.setRequestHeader("x-apikey", my key);
    xhr.setRequestHeader("cache-control", "no-cache");

    xhr.send(data);

    function setRes(resText) {
      this.posts = resText;
      console.log(resText);
    }

  }

}

interface ApiPosts {
  _id: string,
 address: string,
 price: number,
 rooms: number,
 sqmt: number,
 _mock: boolean
}

this is an example of the responseText im getting:

[{
    "_id": "5bc98372f27689550002c99d",
    "address": "979 Parisian Divide Suite 335\nTonistad, TX 33097",
    "price": 1472,
    "rooms": 6,
    "sqmt": 984,
    "_mock": true
}, {
    "_id": "5bc98372f27689550002c9a9",
    "address": "416 Barbara Dale\nLake Velva, GA 83588",
    "price": 2028,
    "rooms": 8,
    "sqmt": 1518,
    "_mock": true
}, {
    "_id": "5bc98372f27689550002c9a3",
    "address": "3109 Amely Stream\nJohnsonmouth, UT 83874",
    "price": 3435,
    "rooms": 11,
    "sqmt": 1891,
    "_mock": true
}]

im doing it on angular 6 if it makes any difference

Bar Levi
  • 1
  • 1
  • 1
  • The `setRes` function is defined within `ngOnInit`, therefore `this` is undefined. You need it as a method of your component. Also, you're not using the Angular way of making HTTP requests (should be through a service, at the very least, and ideally using [`HttpClient`](https://angular.io/guide/http)). – Jeto Oct 20 '18 at 23:02

1 Answers1

1

When using a function within a method, this references something other than the current class see here.

  • in a browser it's the window
  • in node it's global
  • in strict mode it's undefined unless called as a method:
    • window.xxx()

See this snippet for example one outputs undefined the other outputs the window:

'use strict'

function abc() { console.log(this) }

abc() // outputs undefined
window.abc() // outputs the window object

Now if we remove strict, they both output the window:

function abc() { console.log(this) }

abc() // outputs the window object
window.abc() // outputs the window object

What you will need to do is create a reference within the method itself, then use that reference within the function like this:

ngOnInit() {

  // Your other stuff here...

  let $this = this;
  function setRes(resText) {
    $this.posts = resText;
  }
}
Get Off My Lawn
  • 34,175
  • 38
  • 176
  • 338
  • Amazing! Thanks much!,It worked, but If you have a suggestion for an easier method to do the same thing i'll be glad to hear, (Assigning get response to an interface variable) – Bar Levi Oct 21 '18 at 13:09
  • The easier way would be to make `setRes` as it's own method instead of a function inside of the method – Get Off My Lawn Oct 21 '18 at 13:12