子组件的 EventEmitter“失去”了父组件的观察者

问题描述

我有一个父组件,它观察子组件的 Output 事件发射器 (topicsChanged)

父组件:

import {
  ChangeDetectionStrategy,Component,EventEmitter,Input,OnInit,Output
} from "@angular/core";
import { Language } from "../language";
import { Templatetopic } from "../template-topic";

@Component({
  selector: "at-main-topics",templateUrl: "./main-topics.component.html",changeDetection: ChangeDetectionStrategy.OnPush
})
export class MainTopicsComponent implements OnInit {
  @input() templates: string[] = [];
  @input() templatetopics: Templatetopic[] = [];
  @input() languages: Language[] = [];
  @Output() templatetopicChanged = new EventEmitter<Templatetopic>();

  constructor() {}

  ngOnInit(): void {}

  get availableTemplatetopics(): Templatetopic[] {
    return this.templates
      .map(x => +x)
      .map(template => {
        const existingTopic = this.templatetopics.find(
          x => x.template === template
        );

        return (
          existingTopic || 
          { //observer will disappear for this empty created object.
            template: template,topics: []
          }
        );
      });
  }

  onTopicsChanged(templatetopic: Templatetopic) {
    // This will not be triggered for 3rd template which is created in availableTemplatetopics getter,because it doesn't exist in initial data (templatetopics)
    this.templatetopicChanged.emit(templatetopic);
  }
}

  <at-template-topic *ngFor="let templatetopic of availableTemplatetopics"
                     [templatetopic]="templatetopic"
                     [languages]="languages"
                     (topicsChanged)="onTopicsChanged($event)">
  </at-template-topic>

一个奇怪的情况下,这个事件发射器失去了它的父组件的观察者。那就是 - 在子组件中我打开一个对话框。在打开对话框之前,如果我检查发射器,观察者在那里,但是一旦对话框关闭,观察者就消失了。

子组件:

import { Component,Output } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { Language } from '../language';
import { Templatetopic } from '../template-topic';
import { Topic } from '../topic';
import { TranslationDialogModel } from '../translation-dialog.model';
import { TranslationDialogComponent } from '../translation-dialog/translation-dialog.component';

@Component({
  selector: 'at-template-topic',templateUrl: './template-topic.component.html'
})
export class TemplatetopicComponent implements OnInit {
  @input() templatetopic: Templatetopic;
  @input() languages: Language[] = [];
  @Output() topicsChanged = new EventEmitter<Templatetopic>();

  private dialogTitle: string = 'lorem ipsum'

  constructor(
    private dialog: MatDialog
  ) { }

  ngOnInit(): void {
  }

  onCreatetopic(): void {
    this.openDialog();
  }

  onEditTopic(topic: Topic): void {
    this.openDialog(topic);
  }

  private openDialog(topic?: Topic): void {
    // this.topicsChanged always has observer at this point
    const dialogRef = this.dialog.open(TranslationDialogComponent,{
      data: {
        pageTitle: this.dialogTitle,availableLanguages: this.languages,translations: topic?.translations
      } as TranslationDialogModel
    });

    dialogRef
      .beforeClosed()
      .subscribe(translations => {
        if (translations) {
          if (topic) {
            topic.translations = translations;
            topic.title = translations[0].title;
          } else {
            this.templatetopic.topics.push({ translations,title: translations[0].title })
          }
          // When called via onCreatetopic method for a category which was created as an empty placeholder,this.topicsChanged has lost it's observer. However if category had initial data,then observer is still there.
          this.topicsChanged.emit(this.templatetopic);
        }
      })
  }
}

对话框中没有任何可疑之处,它只是返回一些数据,仅此而已。这以某种方式连接到父组件中的 getter get availableTemplatetopics,从中创建子组件列表。在 getter 中有一个代表每个子组件的模板列表,这些子组件要么从现有数据填充,要么创建一个空的占位符。问题在于空的占位符对象。

片段:

  get availableTemplatetopics(): Templatetopic[] {
    return this.templates
      .map(x => +x)
      .map(template => {
        const existingTopic = this.templatetopics.find(
          x => x.template === template
        );

        return (
          existingTopic || 
          { //observer will disappear for this empty created object.
            template: template,topics: []
          }
        );
      });
  }

我发现我可以通过将 getter 逻辑上移一级来解决所有这些问题,但我仍然想了解这种奇怪的行为。观察者怎么会就这样消失,它是如何连接到吸气剂的?

完整代码的 Stackblitz:https://stackblitz.com/edit/angular-kjewu7?file=src/app/main-topics/main-topics.component.ts

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)