是否可以抽象出模板的公共部分?
Is it possible to abstract out common parts of template?
例如,我有多个用于分页的组件collections。模板示例:
<div *ngIf="!isFormVisible">
<button class="btn" [ngClass]="{'btn-info': filtered, 'btn-default': !filtered}" (click)="showForm()">Filter</button>
<button class="btn btn-default" (click)="createNew()">Create new</button>
</div>
<div class="panel panel-default" *ngIf="isFormVisible">
<div class="panel-heading">
<h3 class="panel-title">Filter<button type="button" class="close" (click)="hideForm()">×</button></h3>
</div>
<div class="panel-body form-horizontal">
<form (ngSubmit)="onFormSubmit()">
<fieldset>
<div class="form-group">
<label class="control-label col-md-2" for="id">Id</label>
<div class="controls col-md-10">
<input type="text" class="form-control [(ngModel)]="filter.id"/>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" for="userName">Username</label>
<div class="controls col-md-10">
<input type="text" class="form-control" [(ngModel)]="filter.userName"/>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button type="submit" class="btn btn-default">Filter</button>
<button type="reset" class="btn btn-default" (click)="onFormReset()">Reset</button>
</div>
</div>
</fieldset>
</form>
</div>
</div>
<div *ngIf="busy">
<h1><i class="fa fa-spinner fa-spin fa-pull-left"></i> Loading...</h1>
</div>
<label *ngIf="!currentQuery.result?.length && !busy">No results</label>
<div class="table-responsive" *ngIf="currentQuery.result?.length && !busy">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>
<a href="javascript:void(0);" (click)="sortBy('id')">Id</a>
</th>
<th>
<a href="javascript:void(0);" (click)="sortBy('userName')">Username</a>
</th>
<th></th>
</tr>
</thead>
<tbody>
<tr *ngFor="#user of currentQuery.result">
<td>{{user.id}}</td>
<td>{{user.userName}}</td>
<td><button class="btn btn-default btn-xs" (click)="manageUser(user.id)">Manage</button></td>
</tr>
</tbody>
</table>
</div>
<pagination [currentPage]="currentQuery.pageIndex" [totalPages]="currentQuery.totalPages" (onPageClick)="onPageClick($event)"></pagination>
对于特定组件,我只对过滤器输入字段、table header 和行模板感兴趣。对所有组件重复所有其余部分。是否有可能以某种方式将 DRY 原则应用于模板并抽象出重复部分?
如果您需要将其他部分作为输入,您可以为这些不同的部分创建组件并利用 ng-content
。
这是一个示例:
@Component({
selector: 'test'
template: `
<div>
<ng-content></ng-content>
</div>
`
})
export class TestComponent {
}
您可以在另一个组件中以这种方式使用此组件:
<test>
<div>
Part to include in the test component template (see ng-content)
</div>
</test>
在你的情况下,它可能是这样的:
<pageLayout>
<form (ngSubmit)="onFormSubmit()">
<fieldset>
<div class="form-group">
<label class="control-label col-md-2" for="id">Id</label>
<div class="controls col-md-10">
<input type="text" class="form-control [(ngModel)]="filter.id"/>
</div>
</div>
(...)
</pageLayout>
PageLayoutComponent 组件的模板可能如下所示:
<div *ngIf="!isFormVisible">
<button class="btn" [ngClass]="{'btn-info': filtered, 'btn-default': !filtered}" (click)="showForm()">Filter</button>
<button class="btn btn-default" (click)="createNew()">Create new</button>
</div>
<div class="panel panel-default" *ngIf="isFormVisible">
<div class="panel-heading">
<h3 class="panel-title">Filter<button type="button" class="close" (click)="hideForm()">×</button></h3>
</div>
<div class="panel-body form-horizontal">
<ng-content></ng-content>
</div>
</div>
您可以添加 <ng-content>
进行嵌入。
@Component({
selector: 'reuse-cmp',
...
template: `
<div>some fixed content</div>
<ng-content></ng-content>
<div>some fixed content in the middle</div>
<ng-content select=".below"></ng-content>
<div>some fixed content below</div>
`
})
class ReusablePart {}
然后像这样使用它
<reuse-cmp>
<other-dynamic-content class="below"></other-dynamic-content>
<dynamic-content></dynamic-content>
</resue-cmp>
Transclusion 将所有具有 class below
的顶级元素放置在该标记为 <ng-content select=".below"></ng-content>
的位置,其余不匹配特定选择器的元素位于 <ng-content></ng-content>
被放置。
例如,我有多个用于分页的组件collections。模板示例:
<div *ngIf="!isFormVisible">
<button class="btn" [ngClass]="{'btn-info': filtered, 'btn-default': !filtered}" (click)="showForm()">Filter</button>
<button class="btn btn-default" (click)="createNew()">Create new</button>
</div>
<div class="panel panel-default" *ngIf="isFormVisible">
<div class="panel-heading">
<h3 class="panel-title">Filter<button type="button" class="close" (click)="hideForm()">×</button></h3>
</div>
<div class="panel-body form-horizontal">
<form (ngSubmit)="onFormSubmit()">
<fieldset>
<div class="form-group">
<label class="control-label col-md-2" for="id">Id</label>
<div class="controls col-md-10">
<input type="text" class="form-control [(ngModel)]="filter.id"/>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" for="userName">Username</label>
<div class="controls col-md-10">
<input type="text" class="form-control" [(ngModel)]="filter.userName"/>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button type="submit" class="btn btn-default">Filter</button>
<button type="reset" class="btn btn-default" (click)="onFormReset()">Reset</button>
</div>
</div>
</fieldset>
</form>
</div>
</div>
<div *ngIf="busy">
<h1><i class="fa fa-spinner fa-spin fa-pull-left"></i> Loading...</h1>
</div>
<label *ngIf="!currentQuery.result?.length && !busy">No results</label>
<div class="table-responsive" *ngIf="currentQuery.result?.length && !busy">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>
<a href="javascript:void(0);" (click)="sortBy('id')">Id</a>
</th>
<th>
<a href="javascript:void(0);" (click)="sortBy('userName')">Username</a>
</th>
<th></th>
</tr>
</thead>
<tbody>
<tr *ngFor="#user of currentQuery.result">
<td>{{user.id}}</td>
<td>{{user.userName}}</td>
<td><button class="btn btn-default btn-xs" (click)="manageUser(user.id)">Manage</button></td>
</tr>
</tbody>
</table>
</div>
<pagination [currentPage]="currentQuery.pageIndex" [totalPages]="currentQuery.totalPages" (onPageClick)="onPageClick($event)"></pagination>
对于特定组件,我只对过滤器输入字段、table header 和行模板感兴趣。对所有组件重复所有其余部分。是否有可能以某种方式将 DRY 原则应用于模板并抽象出重复部分?
如果您需要将其他部分作为输入,您可以为这些不同的部分创建组件并利用 ng-content
。
这是一个示例:
@Component({
selector: 'test'
template: `
<div>
<ng-content></ng-content>
</div>
`
})
export class TestComponent {
}
您可以在另一个组件中以这种方式使用此组件:
<test>
<div>
Part to include in the test component template (see ng-content)
</div>
</test>
在你的情况下,它可能是这样的:
<pageLayout>
<form (ngSubmit)="onFormSubmit()">
<fieldset>
<div class="form-group">
<label class="control-label col-md-2" for="id">Id</label>
<div class="controls col-md-10">
<input type="text" class="form-control [(ngModel)]="filter.id"/>
</div>
</div>
(...)
</pageLayout>
PageLayoutComponent 组件的模板可能如下所示:
<div *ngIf="!isFormVisible">
<button class="btn" [ngClass]="{'btn-info': filtered, 'btn-default': !filtered}" (click)="showForm()">Filter</button>
<button class="btn btn-default" (click)="createNew()">Create new</button>
</div>
<div class="panel panel-default" *ngIf="isFormVisible">
<div class="panel-heading">
<h3 class="panel-title">Filter<button type="button" class="close" (click)="hideForm()">×</button></h3>
</div>
<div class="panel-body form-horizontal">
<ng-content></ng-content>
</div>
</div>
您可以添加 <ng-content>
进行嵌入。
@Component({
selector: 'reuse-cmp',
...
template: `
<div>some fixed content</div>
<ng-content></ng-content>
<div>some fixed content in the middle</div>
<ng-content select=".below"></ng-content>
<div>some fixed content below</div>
`
})
class ReusablePart {}
然后像这样使用它
<reuse-cmp>
<other-dynamic-content class="below"></other-dynamic-content>
<dynamic-content></dynamic-content>
</resue-cmp>
Transclusion 将所有具有 class below
的顶级元素放置在该标记为 <ng-content select=".below"></ng-content>
的位置,其余不匹配特定选择器的元素位于 <ng-content></ng-content>
被放置。