Subject subscribe is not triggering in a component

8.1k views Asked by At

When I am trying to subscribe to Subject folder_id, it is not subscribing in the board component when I am passing the id in the files component.

This boardId function is triggered when a button is pressed in the files component. The activateId is the id taken from the snapshot of the url.

  boardID(){
    this.apiService.folder_id.next(this.activateID.id);
    console.log(this.activateID.id);
  }

This is the ngOnInit in the boards component which has to subscribe the id that is emitted from the files component. But for some reason when I try to get the id in this component, it does not run this subscribe function.

  ngOnInit() {
    
    this.apiService.folder_id.subscribe(
      (_id : string) => {
       this.id = _id;
       console.log(this.id)
       
     }
   );

    this.page = 0;
    console.log('Screen width :', this.scrWidth, 'Screen height', this.scrHeight);

    // getting the 2D context of Canvas element
    this.canvasElement = this.canvas.nativeElement;
    this.ctx = this.canvasElement.getContext('2d');
    // setting the Width and Height to the canvas element
    this.renderer.setAttribute(this.canvasElement, 'width', this.scrWidth);
    this.renderer.setAttribute(this.canvasElement, 'height', this.scrHeight);

    // for background
    this.backgroundCanvas = this.background.nativeElement;
    this.renderer.setAttribute(this.backgroundCanvas, 'width', this.scrWidth);
    this.renderer.setAttribute(this.backgroundCanvas, 'height', this.scrHeight);

  }

Now this is the service.ts file :-

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Router } from '@angular/router';
import { environment } from 'src/environments/environment';
import { Subject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class RestService {

  xAuthToken = null;
  boardId = null;
  gerBoardDetails = null;
  createFolderResponse = null;
  deleteFolderResponse = null;

  folder_id = new Subject<string>();
  
  constructor(private http: HttpClient, public router: Router) {}

Can someone please help me on this issue, I am stuck on this for many days now. Thank you.

3

There are 3 answers

0
abolfazl_mehdi On
    at RestService you must make 2 function methode
     1. setData(data: string ) {
       this.folder_id.next(data)
      }
    
     2. getData(res): Subscription {
     return this.folder_id.subscribe(res) 
     }

    and call getData function in your component 
    this.RestService.getData(res => { 
      console.log(res)
    })
0
Tombery On

You should first turn your Subject into an Observable as follow:

folder_id$ = this.apiService.folder_id.asObservable();

And then subscribe to it in your onInit:

this.apiService.folder_id$
    .subscribe((_id : string) => {
        this.id = _id;
        console.log(this.id) 
    }

But, if you subscribe to this observable after a value was emitted, you will not see it because the value was emitted before you subscribed to it. In this case, you should use a ReplaySubject to emit previous values.

0
viniciusmfelix On

You should declare your subscribe method inside your constructor method, other way it will run just once (during the ngOnInit phase) and, if your subscribe does not catch any value during this execution, it will not catch any other else. Declaring the the subscribe method on the constructor, you will be able to watch every event emitted.

Then, if I understand correctly your problem, you want to emit the Subject from the service to the component. For that, you will need to have a Subject type on your service AND an Observable type on your component, so you are able to listen the events emitted from the Subject. Also, will need to provide your subject as an Observable so you can watch it.

Try to refactor your code like this:

Service.ts

folder_id = new Subject<string>();

emitFolderId(id: string) {
  this.folder_id.next(id);
}

getObservable() {
  return this.folder_id.asObservable();
}

Component.ts

folder_id$: Observable<string>;

id: string;

constructor(private apiService: RestService) {
  folder_id$ = apiService.getObservable();
  folder_id$.subscribe(folder_id => {
      this.id = folder_id;
    }
  );
}

boardID() {
  this.apiService.emitFolderId(this.id);
}

Then, you should have your ID rendered correctly.

If you are not sure if your component is rendered when your Subject comes up, try to replace Subject to BehaviourSubject.

The BehaviourSubject will provide the last value to his watchers when is no other active, so you will be able to watch the every last value emmited from the BehaviourSubject, the only difference that you shold instantiate it with a starter value so it can emit the first value when it is instantiate.

folder_id = new BehaviourSubject<string>(null);