Skip to content

Instantly share code, notes, and snippets.

@ericjeker
Created March 13, 2020 06:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ericjeker/fcd59a31955dd89b41536964dde05319 to your computer and use it in GitHub Desktop.
Save ericjeker/fcd59a31955dd89b41536964dde05319 to your computer and use it in GitHub Desktop.
Full example of a customizable component using TemplateRef and ContentChild in Angular
<div id="articles-list">
<!-- Our page carded component -->
<app-page-carded>
<ng-template #title>
<h1>Users List</h1>
</ng-template>
<ng-template #search>
<!-- Display a search box -->
<app-list-search [listForm]="listForm"></app-list-search>
<!-- Display a modal form containing our filters -->
<app-list-filters [listForm]="listForm"></app-list-filters>
</ng-template>
<ng-template #actions>
<!-- Some actions we want to add on the list -->
<button [routerLink]="'/articles/new'"><mat-icon>add</mat-icon></button>
</ng-template>
<ng-template #content>
<!-- And finally our list and a pagination -->
<app-users-list [dataSource]="dataSource"></app-users-list>
<mat-paginator (page)="onPageEvent($event)"></mat-paginator>
</ng-template>
</app-page-carded>
</div>
@Component({
selector: 'articles',
templateUrl: './articles.component.html',
styleUrls: ['./articles.component.scss']
})
export class ArticlesComponent implements OnInit, OnDestroy {
public dataSource: Article[];
/**
* listForm is a FormGroup, by subscribing to its valueChanges we can
* refresh the dataSource every time the filters or search are changed.
**/
protected listForm: FormGroup;
}
<ng-container>
<div class="header">
<div class="title">
<ng-container *ngTemplateOutlet="titleTemplate"></ng-container>
</div>
<div class="actions">
<ng-container *ngTemplateOutlet="actionsTemplate"></ng-container>
</div>
<div class="search">
<ng-container *ngTemplateOutlet="searchTemplate"></ng-container>
</div>
</div>
<div class="content">
<ng-container *ngTemplateOutlet="contentTemplate"></ng-container>
</div>
</ng-container>
@Component({
selector: 'app-page-carded',
templateUrl: 'page-carded.component.html',
stylesUrl: 'page-carded.component.scss',
ViewEncapsulation.None,
})
class PageCarded {
@ContentChild('title', {static: true}) titleTemplate: TemplateRef;
@ContentChild('actions', {static: true}) actionsTemplate: TemplateRef;
@ContentChild('search', {static: true}) searchTemplate: TemplateRef;
@ContentChild('content', {static: true}) contentTemplate: TemplateRef;
}
@ericjeker
Copy link
Author

ericjeker commented Mar 13, 2020

Not sure if this is very clear but basically, we create a PageCarded component and reuse it in ArticlesComponent by passing different templates as ContentChild. These templates are injected in PageCarded using the ngTemplateOutlet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment