Can't update list in Angular 2 using Observable

473 views Asked by At

I am using angular 2 and socket.io together for loading data and reload changes using socket.io

I have a service for loading data from API:

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';
import * as io from 'socket.io-client';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import { Call } from '../model/call';
import * as globals from '../../globals';

@Injectable()
export class CallService {

  private socket;

  constructor(private http: Http) { }

    /**
     * Load all calls data from server.
     * @method loadCalls
     *
     * @return {Observable<Call[]>}
     */
  loadCalls(): Observable<Call[]> {
    return this.http
      .get(globals.server + globals.apiRoutes['calls'])
      .map(res => {
        return res.json();
      });
  }

  /**
   * Observer for call's mission time changing
   * @method callObserver
   * @return {Observable<any>}
   */
  callObserver() :Observable<any>{
    let observable = new Observable(observer => {
      this.socket = io.connect(globals.socketioServer);
      this.socket.on('call-channel:App\\Events\\CallEvent' , data => {
        observer.next(data);
      });
      return () => {
        this.socket.disconnect();
      }
    });
    return observable;
  }

}

The loadCalls method , loads all calls data at the startup of application and the callObserver method listens for any broadcasted changes from server. The call-component.ts file is:

import { Component, OnInit, OnDestroy ,Input} from '@angular/core';
import * as io from 'socket.io-client';
import { CallService } from './service/call.service';
import { Call } from './model/call';
import { Observable } from 'rxjs/Observable';

@Component({
  selector: 'app-call-status',
  templateUrl: './call-status.component.html',
  styleUrls: ['./call-status.component.css'],
  providers: [
    CallService,
  ],
})
export class CallStatusComponent implements OnInit, OnDestroy  {

  private connection;

  private calls: Call[] = new Array();

  private noMissionCalls: Call[] = new Array();

  private backToBaseCalls: Call[] = new Array();

  private finishMissionCalls: Call[] = new Array();

  private deliveredpatientCalls: Call[] = new Array();

  private arriveHospitalCalls: Call[] = new Array();

  private moveFromCalls: Call[] = new Array();

  private arrivedCalls: Call[] = new Array();

  private startMissionCalls: Call[] = new Array();

  private notifyMissionCalls: Call[] = new Array();

  constructor(private callService: CallService) {

  }

  ngOnInit() {

    this.classifyCalls(); //load calls data

    //listen for changes from server
    this.connection = this.callService.callObserver().subscribe(function(res) {
      let call: Call = res.data ? res.data[0] : null;
      if (call) {
        console.log(call);
      }

    });


  }

  ngOnDestroy() {
    this.connection.unsubscribe();
  }


  classifyCalls() {

    this.calls = new Array();
    this.noMissionCalls = new Array();
    this.backToBaseCalls = new Array();
    this.finishMissionCalls = new Array();
    this.deliveredpatientCalls = new Array();
    this.arriveHospitalCalls = new Array();
    this.moveFromCalls = new Array();
    this.arrivedCalls = new Array();
    this.startMissionCalls = new Array();
    this.notifyMissionCalls = new Array();

    this.callService.loadCalls().subscribe(calls =>{
      for(let item of calls){
        this.classifySingleCall(item);
      }
    });
  }

  classifySingleCall(call: Call) {
    if (call.mission_times == null) {
      call.status_name = 'noMissionCalls'
      this.noMissionCalls.push(call);

    } else if (call.mission_times.back_base) {
      call.status_name = 'backToBaseCalls';
      this.backToBaseCalls.push(call);

    } else if (call.mission_times.finish_mission) {
      call.status_name = 'finishMissionCalls';
      this.finishMissionCalls.push(call);

    } else if (call.mission_times.deliver_patient) {
      call.status_name = 'deliveredpatientCalls';
      this.deliveredpatientCalls.push(call);

    } else if (call.mission_times.arrive_hospital) {
      call.status_name = 'arriveHospitalCalls';
      this.arriveHospitalCalls.push(call);

    } else if (call.mission_times.move_from) {
      call.status_name = 'moveFromCalls';
      this.moveFromCalls.push(call);

    } else if (call.mission_times.arrived_urgency) {
      call.status_name = 'arrivedCalls';
      this.arrivedCalls.push(call);

    } else if (call.mission_times.start_mission) {
      call.status_name = 'startMissionCalls';
      this.startMissionCalls.push(call);

    } else if (call.mission_times.notify_mission || call.mission_times.get_message) {
      call.status_name = 'notifyMissionCalls';
      this.notifyMissionCalls.push(call);

    } else {
      call.status_name = 'noMissionCalls';
      this.noMissionCalls.push(call);
    }

    return call;
  }


}

Loading data done at the startup of application. But the problem is here: When a call change broadcasted to all clients , I can receive this call's data using this code that places in ngOnInit()

 this.connection = this.callService.callObserver().subscribe(function(res) {
      let call: Call = res.data ? res.data[0] : null;
      if (call) {
        console.log(call);//log the call

        console.log(this.calls);//undefined
      }

    });

But I can'n access the this.calls data in the if statement of the code. The calls data loaded in the first line of ngOnInit. How can I access data filled by this.classifyCalls(); method?

1

There are 1 answers

3
Poul Kruijt On BEST ANSWER

Don't use the word function when inside classes while using typescript. This replaces the this context of the class to that of the function you just defined. Use the arrow notation:

this.connection = this.callService.callObserver().subscribe((res) => { //<-- here
   let call: Call = res.data ? res.data[0] : null;
   if (call) {
      console.log(call);//log the call
       console.log(this.calls);//undefined
   }

});