ค้นหาเว็บไซต์

typescript - การแชร์ข้อมูลระหว่างคอมโพเนนต์โดยใช้ Angular service สำหรับ Ajax Datatables


ฉันเป็นมือใหม่ในสาขา Angular! จนถึงตอนนี้ฉันชอบมัน แต่กำลังเจอกับความยากลำบากในกรณีต่อไปนี้ ฉันต้องการส่งข้อมูลจากคอมโพเนนต์หนึ่งไปยังคอมโพเนนต์อีกตัวหนึ่งเมื่อผู้ใช้คลิกที่เซลล์เฉพาะที่มีแท็ก href ใน Datatables ดังนั้นฉันจึงได้สร้างไฟล์ .ts ดังต่อไปนี้

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(){
  }
}

บริการของฉันสามารถรับข้อมูลได้ แต่ตัวรับข้อมูลมักจะส่งค่ากลับเป็น null ฉันอยากรู้จริงๆ ว่ามีอะไรผิดพลาดตรงไหน! ฉันซาบซึ้งจริงๆ กับความช่วยเหลือและคำแนะนำของคุณ!

อัปเดต ตามที่ DeborahK แนะนำให้รวมส่วนของโครงการใน Stackblitz! คุณสามารถดูว่าฉันกำลังพยายามสร้างโครงการนี้อย่างไร!

สแต็กบลิทซ์

คำตอบ #1

มีปัญหาบางอย่าง วิธีที่ง่ายคือถ้าคุณกำลังสมัครสมาชิกกับ sendProtData().subscribe ใน receiver.ts นั่นไม่ถูกต้อง คุณจำเป็นต้องสมัครสมาชิกกับ BehaviorSubject และ sendProtData() ก็ ไม่มีประเภทการคืนค่า เช่นกัน

ทำให้ protDataSource เป็นสาธารณะและสมัครใช้งานมัน

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

และจากนั้นใน receiver.ts:

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

นี่ก็ได้ผลเช่นกัน

อัปเดต :

ตรวจสอบเดโมที่ทำงานนี้

ฉันแก้ไขสิ่งต่อไปนี้เพื่อให้มันใช้งานได้:

  1. คุณไม่ควรฉีดบริการโดยใช้ provider:[] ใน @Component เพราะมันจะสร้างอินสแตนซ์ใหม่ของบริการสำหรับแต่ละคอมโพเนนต์ ซึ่งคุณไม่ต้องการแบบนั้น คุณต้องการให้ทั้งสองคอมโพเนนต์แชร์อินสแตนซ์ของบริการเดียวกันเพื่อแชร์ข้อมูล ดังนั้นควรฉีดใน @NgModule ใน app.module.ts

  2. ในโค้ดตัวอย่าง ไม่มี <app-receiver></app-receiver> ผมได้เพิ่มอันนั้นเข้าไปด้วยเพื่อเริ่มต้นคอมโพเนนต์

ฉันหวังว่ามันจะช่วยได้นะ :) ขอบคุณที่สร้างเดโม

คำตอบ #2

ลองย้าย console.log ของคุณ:

แทนที่จะเป็นสิ่งนี้:

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

  }

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

ลองอันนี้:

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