【问题标题】:Angular 2 : How do I send childComponent properties to parent when you don't know the childComponent's class?Angular 2:当您不知道 childComponent 的类时,如何将 childComponent 属性发送给 parent?
【发布时间】:2016-10-18 13:28:58
【问题描述】:

好的,这就是我想要实现的目标:

我有这个组件:

import { Component, Output, EventEmitter, OnInit } from '@angular/core';

@Component({
  selector: 'like',
  template: '<p>this is the like component<p>'      
})

export class LikeComponent implements OnInit{
  title: string = 'Like Component';

  @Output() sendTitle = new EventEmitter();

  ngOnInit() {
    this.sendTitle.emit({title: this.title});
  }    
}

我想将标题从它发送给父母:

import { Component, Input } from '@angular/core';

@Component({
  moduleId: module.id,
  selector: 'panel',
  template: `
      <div class="panel panel-default">
        <div class="panel-heading">
          <h2 class="panel-title">{{title}}</h2>
        </div>
        <div class="panel-body">
          <ng-content (sendTitle) = "receiveTitle($event)"></ng-content>
        </div>
      </div>
  `
})
export class PanelComponent {
  title = 'default title';

  receiveTitle(arg) {
    this.title = arg.title;
    console.log(arg);
  }
}

然后我可以将PanelComponent 与我想包装在面板中的每个组件一起重用:

<panel>
    <like></like>
</panel>

<panel>
    <another-component></another-component>
</panel>

<panel>
    <exemple-component></exemple-component>
</panel>

每次显示Panel 组件时,它都会尝试从事件中获取标题(如果存在)。

这似乎不适用于 ng-content,因为它与常规父/子组件一样?我对 angular 2 不熟悉,因此非常感谢您的反馈!

tl;dr :我想让父母知道孩子的属性,但孩子不能具体(这就是我使用&lt;ng-content&gt; 的原因)。

简而言之,我不想像这样通过input 这样做:

<panel [title] = "'This is the panel title of the like component'">
    <like></like>
</panel>

<panel [title] = "'This is the panel title of the another-component'">
    <another-component></another-component>
</panel>

【问题讨论】:

    标签: angular typescript components parent-child


    【解决方案1】:

    经过大量搜索,我找到了类似 Sasxa 的解决方案,但可以与任何子组件一起使用。关键是@ComponentChild的“选择器”可以是字符串。

    interface TitledComponent {
        title?: string;
    }
    
    @Component({
        selector: 'panel',
        template: `<div class="panel">
                        <h2>{{title}}</h2>
                        <ng-content></ng-content>
                    </div>`
    })
    export class PanelComponent {
        title = 'default title';
    
        @ContentChild('titled') childComponent: TitledComponent;
    
        ngAfterContentInit() {
            if (this.childComponent)
                this.title = this.childComponent.title || 'default title';
        }
    }
    

    而且 html 必须是

    <panel>
        <like #titled></like>
    </panel>
    <panel>
        <other #titled></other>
    </panel>
    <panel>
        <p>I don't have a title</p>
    </panel>
    <panel>
        <like></like>
        <!-- This won't be picked up -->
    </panel>
    

    【讨论】:

    • 哇,谢谢@jladan,这正是我想要的!好主意!
    【解决方案2】:

    试试这个:

    export class PanelComponent {
      title = 'default title';
      @ContentChild(LikeComponent) like: LikeComponent;
    
      ngAfterContentInit() {
        this.title = this.like.title;
      }
    }
    

    【讨论】:

    • 我真的很想使用你的代码,但是因为我想重用 PanelComponent 来包装我想要的所有其他组件,所以这行不通。
    【解决方案3】:

    如果要使用事件方式,可以使用element.dispatchEvent创建冒泡事件。 EventEmitter 事件不会冒泡,只能与 (xxx) 绑定一起使用。

    在子组件中看起来像

      constructor(private elRef:ElementRef, private renderer:Renderer) {}
    
      onBlur($event) {
        this.renderer.invokeElementMethod(this.elRef.nativeElement, 
            'dispatchEvent', 
            [new CustomEvent('input-blur', { bubbles: true })]);
    

    另见我的类似回答in Angular2 how to know when ANY form input field lost focus

    【讨论】:

    • 好吧,我真的不想使用事件,这对我来说似乎是一种可能的方法。我只想从不知道孩子是否可以说title 财产的父母那里获得孩子财产。我想尝试一下,如果它返回一个字符串
    【解决方案4】:

    我认为应该在面板模板中这样做

    <h2>{{title}}</h2>
    <panel class="col-xs-6 col-md-4">
        <like (sendTitle)="receiveTitle($event. title)"></like>
    </panel>
    

    并在组件中设置:

    receiveTitle(title) {
        this.title = title;
        console.log(event);
    }
    

    您像发送(单击)事件一样发送输出事件。 () 表示你从 html 向组件提交一些东西,[] 表示你从组件绑定一些东西到 html。

    希望这就是你的意思!

    不清楚为什么要使用 ng-content ? 每次点击,父标题都会从子组件更新。

    【讨论】:

    • 我正在使用&lt;ng-content&gt;,因为我希望这个组件可以与我想要的任何其他组件一起使用。简而言之,它只是将一个组件包装在一个漂亮的面板中,但我想从孩子那里得到panel-title。从LikeComponent,我虽然可以使用OnInit() { this.sendTitle.emit({title: this.title}); },所以它会在启动时发送标题?或者我应该通过constructor发送它。
    • 我目前看不到没有面板用户支持的方法。如果用户添加了模板变量或属性(以指令为目标),则可以使用@ContentChildren() 对其进行查询。我认为 Angular 团队最终会改进这一点。您不是第一个要求使用此功能的人。
    猜你喜欢
    • 2019-01-03
    • 2021-10-09
    • 2021-01-05
    • 2021-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-17
    • 2019-03-10
    相关资源
    最近更新 更多