角度|如何使用ng-template或其他将ng-content / child内容放置在组件之外

时间:2018-11-07 12:30:47

标签: angular angular2-template

我有一个制表组件,在此定义 https://stackblitz.com/edit/angular-tabs-example

我正在尝试将my-tabs中的ng-content放到外部ng-template中,有什么办法吗?我可以将ng-content分配给TemplateRef或ViewContainerRef。

2 个答案:

答案 0 :(得分:0)

是的,您可以使用@ContentChild角形表单,这将帮助您将内容从父组件传递给子组件-我将稍微更改代码

tabs.component.ts

@Component({
  selector: 'my-tabs',
  template: `
    <ul class="nav nav-tabs">
      <li *ngFor="let tab of tabs" (click)="selectTab(tab)" [class.active]="tab.active">
        <a href="#">{{tab.title}}</a>
      </li>
    </ul>
    <ng-template [ngTemplateOutlet]="parentList"></ng-template>
  `,
  styles: [
    `
    .tab-close {
      color: gray;
      text-align: right;
      cursor: pointer;
    }
    `
  ]
})
export class TabsComponent implements AfterContentInit {

  @ContentChild('list') parentList: TemplateRef<any>;

 }

app.component.ts

@Component({
  selector: 'my-app',
  template: `
    <my-tabs>
      <my-tab [tabTitle]="'Tab 1'">
        Tab 1 content
      </my-tab>
      <ng-template #list>
          <my-tab tabTitle="Tab 2">
             Tab 2 content
          </my-tab>
      </ng-template>
    </my-tabs>
  `
})
export class AppComponent {
}

父组件中的<ng-template #list>会将其内容在模板中传递给子组件-而子组件将读取内容并将其放入<ng-template [ngTemplateOutlet]="parentList"></ng-template>

通过这种方法,您可以将尽可能多的内容从父母传递给孩子-希望这对您有帮助

谢谢-祝您编程愉快! -检查此链接以进一步阐明https://angular.io/api/core/ContentChild

答案 1 :(得分:0)

我使用下面的代码解决了这个问题,我正在使用Output EventEmitter获取ng-content并将其放在父模板中。欢迎任何建议,我需要帮助来改进它。

parent.component.html

<sb-tabs contentMode="external" (templateAfterInit)="tabContentSet($event)">
   <sb-tab *ngIf="jobId" tabTitle="Invoices">
              Hello
   </sb-tab>
</sb-tabs>
侧边栏     显示内容     

parent.component.ts

@ViewChild("tabContent")
  tabContent: TemplateRef<any>;
tabContentSet(event) {
    this.tabContent = event.template;
  }

tabs.component.ts

import {
      Component, AfterContentInit, ContentChildren, QueryList
      , Input, Output, ViewChild, EventEmitter
    } from '@angular/core';

    import { TabComponent } from './tab.component'

    enum TabContentMode { internal = 'internal', external = 'external' }

    @Component({
      selector: 'sb-tabs',
      template: `
      <ul class="nav nav-tabs {{cssClasses.tabsBar}}">
        <li class="nav-item" *ngFor="let tab of tabs" (click)="selectTab(tab)">
          <a class="nav-link" [class.active]="tab.active">{{tab.title}}</a>
        </li>
      </ul>
      <ng-container *ngIf="contentMode == 'internal'" [ngTemplateOutlet]="tabsContent">
      </ng-container>
      <ng-template #tabsContent>
        <ng-content></ng-content>
      </ng-template>
    `
    })
    export class TabsComponent implements AfterContentInit {

      @Input() cssClasses: any = {
        tabsBar: 'nav nav-tabs'
      };

      @ContentChildren(TabComponent) tabs: QueryList<TabComponent>;

      @ViewChild("tabsContent")
      private externalTemplate: any;

      @Input() contentMode: TabContentMode = TabContentMode.internal;

      @Output("templateAfterInit")
      templateAfterInit = new EventEmitter();

      constructor() { }

      ngAfterContentInit(): void {

        this.templateAfterInit.emit({ template: this.externalTemplate });

        // get all active tabs
        let activeTabs = this.tabs.filter((tab) => tab.active);

        // if there is no active tab set, activate the first
        if (activeTabs.length === 0) {
          this.selectTab(this.tabs.first);
        }
      }

      selectTab(tab: TabComponent) {
        // deactivate all tabs
        this.tabs.toArray().forEach(tab => tab.active = false);

        // activate the tab the user has clicked on.
        tab.active = true;
      }

    }

tab.component.ts

import { Component, OnInit, Input } from '@angular/core';
import { fadeInOut } from '@shared/common/animations';

@Component({
  selector: 'sb-tab',
  animations: [fadeInOut],
  template: `
    <div [@fadeInOut] *ngIf="active" class="pane">
      <ng-content></ng-content>
    </div>
  `
})
export class TabComponent implements OnInit {

  @Input('tabTitle') title: string;
  @Input() active = false;


  constructor() { }

  ngOnInit() {
  }

}