在嵌套组件中链接转换

时间:2016-12-20 16:52:32

标签: angular

我有以下嵌套组件的结构。

<app-root>
    <app-comp-1>
      <app-comp-2>
      </app-comp-2>
   </app-comp-1>
  <app-root>

我想将任何内容转换为最后一个孩子(app-comp-2)。所以,我需要这样的东西。

<app-comp-1>
    <app-comp-2>
        <ng-content></ng-content>
    </app-comp-2>
</app-comp-1>

但是在app-root组件中只有app-comp-1组件可用。所以,这是我必须转录我的内容的地方。

<app-root>
    <app-comp-1>
        <content-I-want-to-transclude></content-I-want-to-transclude>
    </app-comp-1>
</app-root>
 ---------------------------
<app-comp-1>
    <ng-content></ng-content>
    <app-comp-2>
        ...
    </app-comp-2>
</app-comp-1>

所以我需要一个解决方案来获取已被转换为第一个组件的内容并将其传递给第二个组件。

Plunker

3 个答案:

答案 0 :(得分:5)

This Github issue使用ngProjectAs属性为此问题提供了一个很好的解决方案。

在具有2层内容投影的情况下,第一层使用带有ng-content属性的ngProjectAs元素,以及下一个选择器。

第二层使用另一个ng-content,并选择第一层ngProjectAs属性的值:

1级(父组件):

<ng-content select="my-component" ngProjectAs="arbitrary-selector"></ng-content>

2级(嵌套子组件):

<ng-content select="arbitrary-selector"></ng-content>

用法:

<my-app>
  <my-component>My Projected Content</my-component>
</my-app>

结果DOM:

<my-app>
  <my-component>
      <nested-component>My Projected Content</nested-component>
  </my-component>
</my-app>

答案 1 :(得分:3)

我遇到了类似的问题,我有一个卡组件,它有一个子卡头组件以及卡体的选择器。

卡片组件有一个切换按钮,用于调度卡片打开/关闭的操作。

然后我需要能够通过卡组件将额外的按钮从父组件传递到卡片头组件中

我通过在每个级别添加选择器来解决它。

首先,我创建了一个通用的card-header组件,允许我有一段代码来处理切换卡内容,通过将操作分派给NgRx存储,该存储包含一系列隐藏的卡(使用提供的名称输入属性)。

toggled状态发生变化时,card-header组件订阅商店并向父组件发出事件

@Component({
  selector: 'po-card-header',
  template: `
    <div class="card-header">

      <span class="text-uppercase">{{ header }}</span>

      <div class="header-controls">
        <ng-content select=[card-header-option]></ng-content>
        <ng-content select=[header-option]></ng-content>

        <span class="header-action" (click)="onTogglePanel()">
         <i class="fa" [ngClass]="{ 'fa-caret-up': !collapsed, 'fa-caret-down': collapsed}"></i>
        </span>

      </div>

    </div>
  `
})
export class CardHeaderComponent implements OnInit, OnDestroy {
  ...
  @Input() name: string;
  @Output() togglePanel = new EventEmitter<boolean>();

  collapsed$: Observable<boolean>;
  collapsedSub: Subscription;

  constructor(private store: Store<State>) {
    this.collapsed$ = this.store.select(state => getPanelCollapsed(state, this.name);
  }

  ngOnInit(): void {
    this.collapsedSub = this.collapsed$.subscribe(collapsed => {
      this.collapsed = collapsed;
      this.togglePanel.emit(collapsed);
    });
  }

  .... unsubscribe on destroy.
}

请注意标题有2 ng-content个部分。

header-option选择器用于我明确使用此组件时要添加的任何其他图标,例如

<div class="card">

  <po-card-header>
    ...
    <span header-option class="fa fa-whatever" (click)="doSomething()"></span>
  </po-card-header>

  ...

</div>

我的新图标将位于标题中的默认切换图标旁边。

第二个card-header-option选择器用于根组件,它使用卡组件,而不是卡头组件,但仍希望将额外的图标传递到标头中。

@Component({
  selector: 'po-card',
  template: `

    <div class="card">
      <po-card-header>
        ...
        <ng-content select="[card-header-option] header-option></ng-content>
      </po-card-header>

      <div class="card-block">
        <ng-content select="[card-body]"></ng-content>
      </div>

    </div>
  `
})
...

[card-header-option]选择器将选择具有该属性的所有元素,然后使用header-option属性

将它们传递到card-header组件中

我的卡组件的最终用法如下所示。

<div>
   Some component that uses the card
   <po-card 
     header="Some text to go in the card header" 
     name="a-unique-name-for-the-card">

     <span card-header-option class='fa fa-blah header-action'></span>

     <div card-body>
       Some content that gets put inside the [card-body] selector on the card component.
     </div>

   </po-card>
</div>

最终的结果是我可以使用我的自定义卡组件,并获得卡头组件提供的切换功能的好处,但也提供我自己的自定义操作,这也将在标题中呈现

希望您觉得有用: - )

答案 2 :(得分:0)

根元素不支持

Transclusion,请参阅this

但是,您可以在所有组件中添加ng-content以传递内容。

@Component({
  selector: 'my-app',
  template: `
  <app-comp-1>
    <app-comp-2>
      <app-comp-3>
         Hello World
      </app-comp-3>
    </app-comp-2>
  </app-comp-1>
  `
})
export class AppComponent { name = 'Angular'; }

@Component({
  selector: 'app-comp-1',
  template: `
   app-comp-1
   <ng-content></ng-content>
  `
})
export class AppComponent1 {  }

@Component({
  selector: 'app-comp-2',
  template: `
   app-comp-2
   <ng-content></ng-content>
  `
})
export class AppComponent2 {  }

@Component({
  selector: 'app-comp-3',
  template: `
   app-comp-3
   <ng-content></ng-content>
  `
})
export class AppComponent3 {  }

请参阅此Plunker

希望这会有所帮助!!