【问题标题】:Angular: Pass Component to a ComponentAngular:将组件传递给组件
【发布时间】:2017-10-11 12:58:21
【问题描述】:

我有这个小网格组件:

@Component({
    selector: 'moving-grid',
    templateUrl: './grid.component.html',
    styleUrls: ['./grid.component.css']
})
  export class GridComponent {
     @Input('widgets') extComponents: Array<Component>;
  }

还有第二个测试组件

@Component({
  selector: 'test',
  template: `
    <div #content>I say hello<li>i</li><li>u</li><button (click)="test()">click me</button> world</div>
  `
})

export class TestComponent {
  @ViewChild('content') content: HTMLElement;

  getContent() {
    return this.content;
  }
  test() {
    console.log("test");
  }
}

现在我正在尝试将 testComponent 的多个实例传递给 gridComponent。因此,我有第三个组件,看起来像这样:

template: `
        <moving-grid [widgets]="[z1,z2]"> 
          <test  class="grid-item-content-001" #z1></test>
          <test  class="grid-item-content-002" #z2></test>
        </moving-grid>
      `

到目前为止,一切都按预期进行。但是如何在 gridComponent 中从 @Input 渲染组件? 我的第一种方法是在 testComponent 中声明一个 @ViewChild 并使用 getContent() 函数返回它。但它不会起作用。我可以以某种方式使用 ng-content 指令还是有更好的解决方案?

GridComponent 看起来像这样。我想在其中一个黑框内显示 @Input-Component 的模板。有可能吗?

感谢您的帮助

【问题讨论】:

标签: angular typescript input nested components


【解决方案1】:

您不应该使用@Input 来传递组件。您可以为此使用@ContentChildren 和摘要WidgetComponent

@Component({
    selector: 'moving-grid',
    template: `
      <div class="widget-wrapper">
         <ng-container *ngFor="let widget of widgets">
             <!-- use a ngSwitchCase here for different types-->
             <grid-test-widget [widget]="widget" *ngIf="widget.active && widget.type === 'test'"></grid-widget>
         </ng-container>          
      </div>
    `,
    styleUrls: ['./grid.component.css']
})
export class GridComponent implements AfterContentInit {
     @ContentChildren('widget')
     widgets: QueryList<WidgetComponent>;

     ngAfterContentInit() {
        //your components will be available here
     }
}

第三个组件的模板将保持不变,但没有 [widgets] 和添加的 #widget 名称:

<moving-grid> 
  <test-widget class="grid-item-content-001" #widget [active]="false"></test>
  <test-widget class="grid-item-content-002" #widget></test>
</moving-grid>

你的 TestWidgetComponent 将扩展一个抽象的 WidgetComponent :

@Component({
  selector: 'test-widget',
  // ...
})
export class TestWidgetComponent extends WidgetComponent {
    public type: string = 'test';
}

还有你的WidgetComponent

@Directive()
export abstract class WidgetComponent {

   @Input()
   public active: boolean;

   public type: string;

}

您将拥有几个基于小部件类型的网格小部件:

@Component({
  selector: 'grid-test-widget',
  template: `<div #content>I say hello<li>i</li><li>u</li><button (click)="test()">click me</button> world</div>`
})
export class GridTestWidgetComponent{}
    

【讨论】:

  • 感谢您的回答。但是我可以通过代码将组件添加到模板中吗?我必须存储组件并在某种事件上显示它们。另外,如果 gridComponent 对 testComponent 一无所知(没有导入标签)会更好
  • 动态添加东西的问题在于它有点妨碍你使用 AoT,而且它也不被视为有角度的方式。也许您应该尝试找到另一种方法来实现您想要的。我会稍微更新一下我的答案,以展示如何动态打开和关闭小部件。但我不确定你想要实现什么
  • 如上图所示,我使用了某种小部件存储(紫色框)。单击它们后,将在下面的空白处添加一个黑框。单击的小部件需要有关将在黑框中呈现哪个组件的信息。所以我需要存储内容。我知道有点混乱。但是感谢您的帮助
  • 我已经更新了我的答案。希望有点道理。但是不,实际上不可能做你想做的事:“存储内容”。例如,如果您使用 [innerHtml],您将失去角度绑定。我希望我的回答能给您提供另一种方式的想法
  • 感谢您的努力。我想我什至无法为这个问题找到更好的解决方案。
猜你喜欢
  • 2019-10-28
  • 1970-01-01
  • 1970-01-01
  • 2016-08-31
  • 2017-10-10
  • 2018-11-25
  • 2019-06-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多