2

I am new in Angular filed! So far I have liked but facing some difficulty in this following case. I want to send data from one component to another component once the user clicks a specific cell with href tag in the Datatables. Therefore I have created following .ts file

service.ts

import { Injectable } from '@angular/core';
import { HttpClient,HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { BehaviorSubject } from 'rxjs';

@Injectable()
export class MyService {

   private protDataSource = new BehaviorSubject<any>({
       currentprotData:null
   });
  currentprotData= this.protDataSource.asObservable();

  constructor(
    private http: HttpClient

  ) {}

  sendProtData(currentprotData:any){
    console.log(currentprotData)
   this.protDataSource.next(currentprotData);
  }
get(url){
   return this.http.get(url)
      .pipe(
          map(responce=>responce),
         catchError(this.handleError)
    )

    }
}

sender.ts

            import { Component, OnInit, OnDestroy, ViewChild, Renderer } from '@angular/core';
            import { ActivatedRoute, Router } from '@angular/router';
            import { DataTableDirective } from 'angular-datatables';
            import { HttpClient,HttpErrorResponse } from '@angular/common/http';
            import { Subject } from 'rxjs';
            import { MyService } from '../qmpkb/qmpkb.service';

            declare var jquery: any;



            @Component({
              selector: 'app-sender-page',
              templateUrl: './sender.component.html',
              styleUrls: ['./sender.component.css'],
              providers:[MyService]
            })
            export class SenderComponent implements OnInit,OnDestroy {
              dtOptions: DataTables.Settings = {};
              dtTrigger: Subject<any> = new Subject();
              private routeSub:any;
              errorStr:Boolean;


              @ViewChild(DataTableDirective)
              datatableElement: DataTableDirective;

              constructor(
                private route: ActivatedRoute,
                private http: HttpClient,
                private renderer: Renderer,
                private router: Router,
                private _myserve:MyService
              ) { }

              ngOnInit(): void {
                    //let destPath='fileapi/resultFile/jsonData/resultJson/'+this.queryResPath
                    let destPath='assets/json/fake.json'
                    this.dtOptions = {
                        pagingType: 'full_numbers',
                        ajax: destPath,
                        processing: true,
                        serverSide: false,
                        columns: [
                            { 
                                title: 'Prot Seq',
                                render: function (data: any, type: any, row: any, meta) {
                                    if (row["Prot Seq"].trim().length > 0 ){
                                        var array =(row["Prot Seq"].trim()).split('<br>');
                                        array.forEach(function(element, index) {
                                            array[index] ='<a target="_blank"   href="/seqfeatures" routerLinkActive="active" seq-link-id=' + element+'>'+element+'</a>';
                                        });
                                        return array.join("<br>");
                                    } else {
                                        return 'No';
                                    }
                                }
                            }
                        ]
                    };



              }

              ngAfterViewInit(): void {
                this.renderer.listenGlobal('document', 'click', (event) => {
                    if (event.target.hasAttribute("seq-link-id")) {
                          this._qmpkb.get(url).subscribe((response: any)=>{
                            this._myserve.sendProtData(response);
                          }, error=>{
                            this.errorStr = error;
                          })
                    }
                })

              }


              ngOnDestroy(){
                  this.routeSub.unsubscribe();
                  this.dtTrigger.unsubscribe();
              }
            }

receiver.ts

    import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { HttpClient,HttpErrorResponse } from '@angular/common/http';
import { MyService } from '../qmpkb/qmpkb.service';
declare var require: any

@Component({
  selector: 'app-prot-view',
  templateUrl: './prot-view.component.html',
  styleUrls: ['./prot-view.component.css'],
  providers:[MyService]
})
export class ProtViewComponent implements OnInit,OnDestroy  {
  message:string
  constructor(
    private route: ActivatedRoute,
    private http: HttpClient,
    private router: Router,
    private _myserve:MyService,
    ) { }

  ngOnInit() {
           this._myserve.currentprotData.subscribe(currentprotData=>{
           this.message=currentprotData
    })

  }




  ngAfterViewInit(): void {
          console.log(this.message)
  }
  ngOnDestroy(){
  }
}

My service can recive data but reciver always retrun null. I am curius to know what is going wrong here! I really apprecite your help and advice!

Updated As DeborahK suggested to include part of project on stackblitz! You can check how I am trying to build this project!

stackblitz

2
  • What does map(responce=>responce) do? Commented Feb 16, 2019 at 11:07
  • @friddo I will receive some HTTP response data from backend in future, thought map may help to get JSON data! Just followed some example to do that! Commented Feb 16, 2019 at 16:09

2 Answers 2

1

There are few problems.Easy way is if you are subscribing to sendProtData().subscribe in receiver.ts that's wrong. You need to subscribe to BehaviorSubject and sendProtData() has no return type as well.

Make protDataSource as public and subscribe to it.

public protDataSource = new BehaviorSubject<any>({
   currentprotData:null
});

and then in receiver.ts:

ngOnInit() {
       this._myserve.protDataSource.subscribe(currentprotData=>{
       this.message=currentprotData
})

This so do the trick.

UPDATE:

Check this working demo

I fixed below things to make it work:

  1. You should not inject service using provider:[] @Component. It creates a new instance of service for each component. . You dont need that. You need both component to share same service instance to share the data. So, inject in @NgModule in app.module.ts

  2. In the demo code, there was no <app-receiver></app-receiver>. I added that as well so as to initiate the component.

I hope it helped :) . Thanks for creating a demo

Sign up to request clarification or add additional context in comments.

9 Comments

Thanks for the advice! I have tried your solution but still at the receiver end, getting following object=>currentprotData:null. Sender still gets that data! I am just wondering whether it is because of ngAfterViewInit() at sender.ts. Any advice to fix it!
@Paul85 can u confirm that this._myserve.sendProtData(response); is being called ? the null value is set while initializing the BehaviorSubject in MyService class. So, may be that value is retained and not the new one which you are expecting. Please check and let me know. You can also try setting some value at initialization of BahviorSubject and see if you are getting that in receiver
@Vivek I think this._myserve.sendProtData(response) is being called because If I do console.log(currentprotData) and console.log(this.protDataSource) inside of sendProtData in sevice.ts, always getting the value which I send from send.ts but somehow its receiver is not receiving that data afterwards! Even I have initialized the BahviorSubject with some value and in this case, only getting that initialized value at the receiver end!
What is calling sendProtData?
@Paul85 : did u try subscribing directly to public protDataSource rather than currentprotData ?
|
0

Try moving your console.log:

Instead of this:

  ngOnInit() {
           this._myserve.sendProtData.subscribe(currentprotData=>{
           this.message=currentprotData
    })

  }

  ngAfterViewInit(): void {
          console.log(this.message)
  }

Try this:

  ngOnInit() {
           this._myserve.sendProtData.subscribe(currentprotData=>{
           this.message=currentprotData;
           console.log(this.message);
    })
  }

6 Comments

I have tried that too but still getting null. Even though I need to use that variable some point of time in ngAfterViewInit () at the receiver side! Anyway, I have edited my code because I realised that I can't use 'this._myserve.sendProtData.subscribe' at the receiver side but need to use this._myserve.currentprotData.subscribe(currentprotData=>{.
Just FYI ... Angular best practices is to normally use the subscribe in the component that needs the data.
thanks for the advice and normally I do but in this case always getting an error Property 'subscribe' does not exist on type '(currentprotData: any) => void'. if I do this._myserve.sendProtData.subscribe
Any way to put a sample of the issue (not the entire application) into a stackblitz so we can take a look?
sure I will do soon
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.