angular2-chapter08

Reusing Components with Content Projection

Check code at: https://github.com/wghglory/angular2-fundamental

Content Projection

Now in event-detail page, there's a list of sessions for that event. We want to collapse and expand every session when clicking the session div. Since this feature is quite common, and probably get reused somewhere else, we need to put this function into common folder.

  1. In session-list.component.html
<div class="row" *ngFor="let session of sessions">
    <div class="col-md-10">
        <!-- content projection -->
        <collapsible-well [title]="session.name">
            <h6>{{session.presenter}}</h6>
            <span>Duration: {{session.duration}}</span><br />
            <span>Level: {{session.level}}</span>
            <p>{{session.abstract}}</p>
        </collapsible-well>
        <!-- <div class="well">
            <h4>{{session.name}}</h4>
            <h6>{{session.presenter}}</h6>
            <span>Duration: {{session.duration}}</span><br />
            <span>Level: {{session.level}}</span>
            <p>{{session.abstract}}</p>
        </div> -->
    </div>
</div>
  1. create common/collapsible-well.component, and register it in module

Note: <ng-content> is responsible to show html inside its selector "collapsible-well": h6+span+span+p in this case

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

@Component({
    selector: 'collapsible-well',
    template: `
        <div (click)="toggleContent()" class="well pointable">
            <h4 class="well-title">{{title}}</h4>
            <ng-content *ngIf="visible"></ng-content>
        </div>
    `
})
export class CollapsibleWellComponent {
    @Input() title: string;
    visible: boolean = true;

    toggleContent() {
        this.visible = !this.visible;
    }
}

Multiple Slot Content Projection

We also want to add a flame icon next to the session title if any session is hot. If we add this feature into collapsible-well template after <h4 class="well-title">{{title}}</h4>, this component is not generic.

session-list.component.html:

well-title and well-body attributes can be used as selectors in collapsible-well.component template. Attribute is better than class since it won't give us any conflict for a css class.

<div class="row" *ngFor="let session of sessions">
    <div class="col-md-10">

        <!-- multi slot content projection -->
        <collapsible-well>
            <div well-title>
                {{session.name}}
                <i *ngIf="session.voters.length>3" class="glyphicon glyphicon-fire" style="color:red;"></i>
            </div>

            <div well-body>
                <h6>{{session.presenter}}</h6>
                <span>Duration: {{session.duration}}</span><br />
                <span>Level: {{session.level}}</span>
                <p>{{session.abstract}}</p>
            </div>
        </collapsible-well>

        <!-- content projection -->
        <!-- <collapsible-well [title]="session.name">
            <h6>{{session.presenter}}</h6>
            <span>Duration: {{session.duration}}</span><br />
            <span>Level: {{session.level}}</span>
            <p>{{session.abstract}}</p>
        </collapsible-well> -->

        <!-- <div class="well">
            <h4>{{session.name}}</h4>
            <h6>{{session.presenter}}</h6>
            <span>Duration: {{session.duration}}</span><br />
            <span>Level: {{session.level}}</span>
            <p>{{session.abstract}}</p>
        </div> -->
    </div>
</div>

collapsible-well.component.ts updates template:

Note: ng-content with select is used to display the html. "select" can have id selector, class selector, etc. Attribute selector is best for multiple slot content projection

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

@Component({
    selector: 'collapsible-well',
    template: `
        <div (click)="toggleContent()" class="well pointable">
            <h4>
                <ng-content select="[well-title]"></ng-content>
            </h4>
            <ng-content *ngIf="visible" select="[well-body]"></ng-content>
        </div>
    `
})
export class CollapsibleWellComponent {
    @Input() title: string;
    visible: boolean = true;

    toggleContent() {
        this.visible = !this.visible;
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 今天和老师沟通了孩子期末考试的情况。语文高分排名前三,很棒~数学滑铁卢,跌到平均分以下,英语也低于平均分。感谢老师...
    爬山虎7544阅读 365评论 0 0
  • 现在p图软件越来越智能,p图越来越方便,效果越来越好,照片p的越来越美,“照片”因此也变成“照骗”了。即使没有任何...
    q肥有大智慧阅读 762评论 2 0
  • 近期目标是财富增长!通过学习智慧和实践智慧并用成功的案例传播智慧,让身边更多的人接受智慧并学习智慧。让世界因智慧而...
    belivePossible阅读 131评论 0 1