What I'm Trying To Do

在我的Angular客户端应用程序中有两个不相关的组件,第一个组件负责从服务器获取和处理数据.我try 使用subscribe回调函数导航到一个新页面并显示处理过的数据(blob).更具体地说,我想转到一个新的标签页,并使用一个无关的组件预览word文档.我发现可以使用带有RxJS主题的服务通过不相关的组件传递数据.

What I'm Getting

我已经实现了一些代码,但是blob没有到达预览组件.

What I've tried

这是我想出的一些代码:

Service for transferring a Blob object

@Injectable()
export class DocPreviewService {
  private blob = new BehaviorSubject<Blob | undefined>(undefined);
  public share$ = this.blob.asObservable();

  constructor() {}

  setBlob(blob: Blob) {
    this.blob.next(blob);
  }
}

Function responsible for retrieving the blob from the server (first component)

  showReport(selected_id: string) {
    const url = this.router.serializeUrl(this.router.createUrlTree([`tools/${selected_id}/preview`]));
    // it's important that the page opens in a new tab
    window.open(url, '_blank');

    this.report_service.createReport(this.calc_items[selected_id]).subscribe({
      next: (doc_blob: Blob) => {
        {          
          this.doc_preview_service.setBlob(doc_blob);
        }
      },
      error: (error: any) => {
      },
    })
  }

Component responsible for viewing a document (second component)

export class DocPreviewComponent implements OnChanges, AfterViewInit, OnDestroy {
  doc_blob?: Blob;
  @ViewChild('doc_preview') doc_preview!: ElementRef;
  subscription: Subscription;
  
  constructor(private doc_preview_service: DocPreviewService, private local_storage: LocalStorageService) {
    this.subscription = this.doc_preview_service.share$.subscribe(blob => {
      this.doc_blob = blob;
    });
  }

  ngOnChanges(changes: SimpleChanges): void {}

  ngAfterViewInit(): void {
    if (this.doc_blob) {
      doc.renderAsync(this.doc_blob, this.doc_preview.nativeElement)
      .then(x => console.log("docx: finished"));
    }
  }

  ngOnDestroy(): void {
    this.subscription.unsubscribe();
  }
}

任何帮助将不胜感激.谢谢

推荐答案

实际上,subject emitter方法有局限性,它只适用于单个选项卡中不相关组件之间的通信,跨选项卡通信是不可能的,因为服务在每个选项卡中会有两个独立的实例,所以永远不会收到事件.

要解决这个问题,您需要做的就是将API调用params附加到URL中

代码打开选项卡

  showReport(selected_id: string) {
    // basically we append the required param needed for making the API 
    // call, then we use it to call the blob logic on the other tab initialization!
    const url = this.router.serializeUrl(this.router.createUrlTree([`tools/${selected_id}/preview?id=${this.calc_items[selected_id]}`]));
    // it's important that the page opens in a new tab
    window.open(url, '_blank');
  }

打开blob的组件将

export class DocPreviewComponent implements OnChanges, AfterViewInit, OnDestroy {
  doc_blob?: Blob;
  @ViewChild('doc_preview') doc_preview!: ElementRef;
  subscription: Subscription;
  
  constructor(private doc_preview_service: DocPreviewService, private local_storage: LocalStorageService) { }

  ngOnChanges(changes: SimpleChanges): void {}

  ngAfterViewInit(): void {
      this.report_service.createReport(this.activatedRoute.snapshot.queryParams.id).subscribe({
         next: (doc_blob: Blob) => {
              this.doc_blob = doc_blob;
              if (this.doc_blob) {
                  doc.renderAsync(this.doc_blob, this.doc_preview.nativeElement)
                  .then(x => console.log("docx: finished"));
              }
         },
         error: (error: any) => {},
     })
  }

  ngOnDestroy(): void {
    this.subscription.unsubscribe();
  }
}

上面的代码可能包含错误,但我希望你采取这种方法并解决你的问题!

Typescript相关问答推荐

如何在Jest中嘲笑location.back()方法调用进行Angular 组件测试?

如何从具有给定键列表的对象类型的联合中构造类型

如果我有对象的Typescript类型,如何使用其值的类型?

扩展函数签名中的参数类型,而不使用泛型

如何缩小变量访问的对象属性范围?

如何正确地对类型脚本泛型进行限制

无法正确推断嵌套泛型?

有没有可能产生输出T,它在视觉上省略了T中的一些键?

布局组件中的Angular 17命名路由出口

按函数名的类型安全类型脚本方法包装帮助器

如何缩小函数的返回类型?

TypeScrip错误:为循环中的对象属性赋值

Typescript 中相同类型的不同结果

如何连接属性名称和值?

如何通过属性名在两个泛型数组中找到匹配的对象?

错误:NG02200:找不到类型为';对象';的其他支持对象';[对象对象]';.例如数组

设置不允许相同类型的多个参数的线性规则

如何在Type脚本中创建一个只接受两个对象之间具有相同值类型的键的接口?

内联类型断言的工作原理类似于TypeScrip中的断言函数?

如何从 Select 元素中删除选项