0

I am following this link on how to use service to make http request in Angular and update my list of items in a component. I can successfully do it with fat arrow function as obserable callback. But when I try to use a method in my component, it failed to update the list of items.

for example:

import { Component, OnInit } from '@angular/core';
import { BlogService } from '../blog.service';
import { Blog } from '../blog';
import { Observable, of } from 'rxjs';

@Component({
  selector: 'app-articles',
  templateUrl: './articles.component.html',
  styleUrls: ['./articles.component.css']
})
export class ArticlesComponent implements OnInit {
  blogs: Blog[];
  constructor(private blogService: BlogService) { }

  ngOnInit() {
    // const handler = (incomingBlogs: Blog[]) => {
    //   this.blogs = incomingBlogs;
    //   console.log("we get: ", this.blogs);
    // }

    const observable: Observable<Blog[]> = this.blogService.getBlogs();
    // observable.subscribe(handler); <===== this will work
    // observable.subscribe(incomingBlogs => {this.blogs = incomingBlogs;  console.log("fat get: ", this.blogs);}); <====== this also work
    observable.subscribe(this.handler); // <===== this failed. 
    console.log("this in init", this);
  }

  handler(incomingBlogs: Blog[]) {
    this.blogs = incomingBlogs;
    console.log("we get: ", this.blogs);
    console.log("this in handler", this); //seems the this keyword refers to something different than the object itself.
  }

}

I tried three approaches to update the list of blogs

  1. fat arrow inside the subscribe as callback. this works!

  2. define a constant and assign a fat arrow function to it. pass it to subscribe function. It works too, just like option 1. And I understand as they behave the same.

  3. define a method in the same class (the component). Use it as callback for the subscribe function. The method is called. But this keyword does not seem to refer to a component. Why is it different? I understand that in the world of javascript, function keyword gives you a whole different this. But why does it happen in a method of a class in TypeScript? Why does the this mean different objects here? Why does fat arrow work ?

I have searched for the answers before but get no luck. (I must haven't used the correct keywords). Thanks for your help!

  • what you meant by failing?are you getting any error in your browser console?? can u please check – Jameel Moideen Aug 26 '18 at 02:36
  • Possible duplicate of [How to access the correct \`this\` inside a callback?](https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback) – ConnorsFan Aug 26 '18 at 02:56

1 Answers1

0

Fat arrow functions always are bound to the object they are defined in, a function will be bound to the object they are called from. Change your handler to an arrow function.

handler = (incomingBlogs: Blog[]) => {
    this.blogs = incomingBlogs;
    console.log("we get: ", this.blogs);
    console.log("this in handler", this); //seems the this keyword refers to something different than the object itself.
  }

If you put a break point in your current function you will see that this points to the observable that it is called from.

If you want to use a normal function you could pass this in as a paramater

  handler(incomingBlogs: Blog[], controller: ArticlesComponent) {
    controller.blogs = incomingBlogs;
    console.log("we get: ", controller.blogs);
    console.log("this in handler", controller); //seems the this keyword refers to something different than the object itself.
  }

But my advice would be to not subscribe to observables in the controller and use the async pipe in your view.

blogs$ = this.blogService.getBlogs();

In your TypeScript and in your view

<ng-container *ngIf="blogs$ | async as blogs">
    Use blogs here as you would have before
    {{blogs | json}}
</ng-container>

Then you have the view managing your subscription for you and you don't have to worry about orphan subscriptions.

Adrian Brand
  • 20,384
  • 4
  • 39
  • 60