0
votes

There seem some similar questions and answers. However, none seems answering mine. I have a mat-table, in each row of it a change was triggered by selecting a option from a dropdown within a mat-cell. And thus I can console.log the data of this specific row with the change.

html:

<mat-row *matRowDef="let row; columns: columnsToDisplay;" 
    (click)="selectDataRow(row);"</mat-row>

service.ts:

private subsSource = new BehaviorSubject<ISubs>(null);
subs$ = this.subsSource.asObservable();

component.ts:

constructor(private subsService: SubsService) { }

selectDataRow(row) {
    console.log(row);
    //to store this row data to the subs$ defined in the service
    this.subsService.subs$ = row;  
}

As expected, the row data was indeed logged to the console.

Now, I want to consume the observable variable "subs$" in another component - ReviewComponent

export class ReviewComponent implements OnInit {

  constructor(private subsService: SubsService) { }

  ngOnInit(): void {  
    this.getSubs();  
  }

  getSubs() {
    this.subsService.subs$.subscribe(res => {
      console.log(res);
    });
}

Unfortunately, I got null log for the subs$ observable from the 2nd component.

Can anyone help point out what I did incorrectly and how to get it work?

2
This looks strange: this.subsService.subs$ = row.. I cannot see a .next() anywhere. I suspect you need something like this. subsSource.next(row) - you’ll have to make that public though.. - MikeOne
Thanks for the solution, Murat. Issue remains. - canbrian
Thanks for the solution, Murat. Issue remains. Can you please take another look? 1) I modified a bit in service.ts: public subs$ = this.subsSource.asObservable(); 2) then tried doing console.log res in the ReviewComponent before the IF condition, got "undifeined" , otherwise, nothing happening 3) I'm not clear about the ngOnDestroy() method in the ReviewComponent, can you clarify? should the "subs" in it suppose to be this.subscriptions if this method is really needed. - canbrian
@canbrian 1) You can also use the methods as set / get like in the answer. 2) It is just checking the value onLoad in order to differentiate. But the value should not be undefined after you set the observable. 3) In the ngOnDestroy(), you destroy the subscribtions in order to prevent from memory leak. I suggest you to have a look at this issue if you use BehaviourSubject Angular Best Practice: Unsubscribing (RxJS Observables). - Murat Yıldız

2 Answers

1
votes

Try this:

private subsSource = new BehaviorSubject<ISubs>(undefined);

getSubsSource(): BehaviorSubject<ISubs> {
    return this.subsSource;
}

setSubsSource(param: any) {
    this.subsSource.next(param);
}

component.ts:

constructor(private subsService: SubsService) { }

selectDataRow(row) {
    console.log(row);
    //to store this row data to the subs$ defined in the service
    this.subsService.setSubsSource(row);
}

export class ReviewComponent implements OnInit {

    private subscriptions = new Subscription();

    constructor(private subsService: SubsService) { }

    ngOnInit(): void {  
        this.getSubs();  
    }

    getSubs() {
        this.subscriptions.add(this.subsService.subs$.subscribe(res => {
            if (res !== undefined) {
                console.log(res);
            }
        });
    }

    ngOnDestroy() {
      subs.forEach(sub => sub.unsubscribe());
    }
}

Hope this helps.

0
votes

Instead of initializing your observable, You need to use your subject:

component.ts:

selectDataRow(row) {
    this.subsService.setSubsSource(row);
}

service.ts:

setSubsSource(row){
    this.subsSource.next(row);
}

Everything else, just like you wrote