简体   繁体   English

从动态创建的子组件向父组件发出事件

[英]Emit event from dynamically created child component to parent component

I have a slider in which are dynamically created items - these are child components. 我有一个滑块,其中是动态创建的项目 - 这些是子组件。

Parent template where is ng-container for slider: 父模板,其中是滑块的ng-container:

<div id="slider-wrapper">
    <ng-container appSliderForm *ngFor="let question of questionsInSlider"
                          [questionTest]="question" (onRemove)="removeQuestion($event)">
    </ng-container>
</div>

These child components are created by appSliderForm directive: 这些子组件由appSliderForm指令创建:

@Directive({
  selector: '[appSliderForm]'
})
export class FormSliderDirective implements OnInit {

  @Input()
  questionTest: QuestionInSlider;

  constructor(private resolver: ComponentFactoryResolver, private container: ViewContainerRef) {}

  ngOnInit(): void {
    const factory = this.resolver.resolveComponentFactory<TestQuestionInSliderComponent>(TestQuestionInSliderComponent);
    const component = this.container.createComponent(factory);
    component.instance.questionTest = this.questionTest;
    component.instance.ref = component;
  }

}

In my child component, I have a remove function for removing itself from a slider. 在我的子组件中,我有一个删除功能,用于从滑块中删除自己。

@Component({
  selector: 'app-test-question-in-slider',
  templateUrl: './test-question-in-slider.component.html',
  styleUrls: ['./test-question-in-slider.component.less']
})
export class TestQuestionInSliderComponent {

  questionTest: QuestionInSlider;

  ref: any;

  @Output() public onRemove = new EventEmitter<QuestionInSlider>();

  constructor(private builderService: FormBuilderService) {}

  /**
   * Chosen question from slider will be displayed.
   */
  choose(): void {
    this.questionTest.chosen = true;
    this.builderService.handlerQuestionFromSlider(this.questionTest);
  }

  remove(): void {
    this.onRemove.emit(this.questionTest);
    this.ref.destroy();
  }

  isChosen() {
    return {'chosen': this.questionTest.chosen};
  }

  getBorderTopStyle() {
     return {'border-top': `4px solid ${this.questionTest.color}`};
  }

}

When this remove function is called by clicking on remove icon in child component template then I would like to emit the event to give a know to parent component to make other operations according to, but the function removeQuestion in parent component is not called. 通过单击子组件模板中的删除图标来调用此删除函数,然后我想发出事件以告知父组件根据其他操作,但不调用父组件中的函数removeQuestion

Could you advise me please why is not called this removeQuestion function? 你能告诉我为什么不叫这个removeQuestion函数?

removeQuestion(question: QuestionInSlider) {
    console.log(question);
  }

UPDATE UPDATE

I've debugged it in the chrome browser and I saw that my onRemove EventEmitter object hadn't any values in his the observers array property when the emit function was called on the onRemove object. 我在chrome浏览器中调试了它,当在onRemove对象上调用emit函数时,我看到我的onRemove EventEmitter对象在他的observers数组属性中没有任何值。

this.onRemove.emit(this.questionTest);

调试

The problem is that the FormSliderDirective does not have an onRemove event. 问题是FormSliderDirective没有onRemove事件。 For your code to work you need to add the event to the directive and subscribe it to the event of the internal component. 要使代码工作,您需要将事件添加到指令并将其订阅到内部组件的事件。 So whenever the internal event fires it will be propagated to the outside. 因此,每当内部事件触发时,它将传播到外部。

Here is a sample how you can add this to your directive: 以下是如何将其添加到指令的示例:

@Directive({
  selector: '[appSliderForm]'
})
export class FormSliderDirective implements OnInit {

  @Input() questionTest: QuestionInSlider;
  @Output() public onRemove = new EventEmitter<QuestionInSlider>();

  constructor(private resolver: ComponentFactoryResolver, private container: ViewContainerRef) {}

  ngOnInit(): void {
    const factory = this.resolver.resolveComponentFactory<TestQuestionInSliderComponent>(TestQuestionInSliderComponent);
    const component = this.container.createComponent(factory);
    component.instance.questionTest = this.questionTest;
    component.instance.onRemove.subscribe(this.onRemove); // this connects the component event to the directive event
    component.instance.ref = component;
  }

}

Perhaps it will help you when the same error happens after applying the solution from @AlesD: 也许它会在从@AlesD应用解决方案后发生同样的错误时帮助您:

ERROR TypeError: Cannot read property 'subscribe' of undefined

The workaround works for me: 解决方法适用于我:

component.instance.onRemove = this.onRemove;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM