【问题标题】:angular5 dynamic compoments parent-chld communicationangular 5 动态组件父子通信
【发布时间】:2018-09-15 00:13:48
【问题描述】:

我正在实施the dynamic compoment docs 中描述的方法。

我需要我的动态组件能够向父组件发出事件,作为响应,父组件可能需要调用子组件的方法。

当子组件在父模板中时,我知道如何将子事件绑定到父方法:

  • @Output() xevent : eventEmitter<string>; 在孩子中
  • <child-comp (xevent)="aParentMethod($event)" 在父模板中

然而在动态组件方法中,父模板包含一个指令,该指令反过来会包装动态实例化的组件。

如何在动态组件上设置@Input 和@Output 属性并将它们从父级传播到子级,反之亦然?

此外,如何让父级调用子级的方法?

【问题讨论】:

    标签: angular dynamic angular5 angular-directive


    【解决方案1】:

    就动态组件而言,角度文档有点过时了。看看 Angular 4 中引入的 [ngComponentOutlet] 指令。它可能会大大简化您的组件。

    简单的用例如下:

    import { Component } from '@angular/core';
    import { HelloComponent } from './hello.component';
    
    @Component({
      selector: 'my-app',
      template: `
        <ng-container [ngComponentOutlet]="component"></ng-container>
      `,
      styleUrls: [ './app.component.css' ]
    })
    export class AppComponent  {
      // [ngTemplateOutlet] binds to this property, you can set this dynamically!
      component = HelloComponent; 
    }
    

    api documentation 中有关 NgComponentOutlet 的更多信息。

    所以这是一个好消息。坏消息是目前无法访问以这种方式创建的组件的@Inputs@Outputs。你可以在 github 上跟踪这个issue

    同时,有人建议使用ng-dynamic-component

    您还可以使用共享服务实现父/子通信:

    app.component.ts

    import { Component } from '@angular/core';
    import {CommunicationService} from './communication.service';
    import {HelloComponent} from './hello.component';
    
    @Component({
      selector: 'my-app',
      template: `
      <input (keydown.enter)="send(input.value); input.value = ''" #input />
      <ng-container [ngComponentOutlet]="component"></ng-container>
      `,
      styleUrls: [ './app.component.css' ]
    })
    export class AppComponent  {
      component = HelloComponent;
    
      constructor(private communicationService: CommunicationService) {}
    
      send(val: string) {
        this.communicationService.next(val);
      }
    }
    

    communication.service.ts

    import {Injectable } from '@angular/core';
    import {Subject} from 'rxjs/Subject';
    import  {Observable } from 'rxjs/Observable';
    
    @Injectable()
    export class CommunicationService {
      private messageSource = new Subject();
      message$ = this.messageSource.asObservable();
    
      next(val: string) {
        this.messageSource.next(val);
      }
    }
    

    hello.component.ts

    import { Component, Input } from '@angular/core';
    import {Observable} from 'rxjs/Observable';
    import {CommunicationService} from './communication.service';
    
    @Component({
      selector: 'hello',
      template: `<h1>{{ message$ | async }} </h1>`,
      styles: [`h1 { font-family: Lato; }`]
    })
    export class HelloComponent  {
      message$: Observable<string>;
    
      constructor(private communication: CommunicationService) {
        this.message$ = communication.message$;
      }
    }
    

    Live demo

    【讨论】:

    • NgComponentOutlet 删除了一些样板,但是由于您无法访问@Input/Output,父子组件如何交互?
    • 嗯,首先想到的是通过服务angular.io/guide/…
    • 为了确保我了解整个情况,AppComponent 构造函数将采用注入服务,子 HelloComponent 也将采用注入服务。还是应该使用 NgComponentOutlet 的 injector 属性?
    • @Cec 我已经使用共享服务通过父/子通信编辑了我的答案。请考虑接受/支持我的回答 :) 创建代码示例需要一些时间。
    • 很高兴我能帮上忙 :)
    猜你喜欢
    • 2016-04-12
    • 2023-03-22
    • 1970-01-01
    • 2018-12-22
    • 2018-09-12
    • 1970-01-01
    • 1970-01-01
    • 2017-10-12
    • 2021-01-15
    相关资源
    最近更新 更多