Last active
August 1, 2021 19:29
-
-
Save ierhalim/297ef69d64e7a64119fcf87579f189de to your computer and use it in GitHub Desktop.
Alternate NgTemplate
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Component, forwardRef, Input, TemplateRef } from '@angular/core'; | |
import { APP_TEMPLATE_CONSUMER_ACCESSOR, TemplateConsumer } from '../models/TemplateConsumer'; | |
@Component({ | |
selector: 'app-my-alternate-list', | |
template: ` | |
<div class="my-list"> | |
<ng-container *ngIf="!!data && data.length > 0 else emptyTemplate"> | |
<div class="list-item" *ngFor="let item of data"> | |
<ng-container *ngTemplateOutlet="itemTemplate;context:{item:item}"></ng-container> | |
</div> | |
</ng-container> | |
</div> | |
`, | |
// Providing the component instance as TemplateConsumer | |
providers: [{ | |
provide: APP_TEMPLATE_CONSUMER_ACCESSOR, | |
useExisting: forwardRef(() => MyAlternateListComponent) | |
}] | |
}) | |
export class MyAlternateListComponent implements TemplateConsumer { | |
@Input() | |
data: Array<unknown>; | |
itemTemplate: TemplateRef<unknown>; | |
emptyTemplate: TemplateRef<unknown>; | |
private readonly templateNameSetters = { | |
item: (templateRef: TemplateRef<unknown>) => { | |
this.itemTemplate = templateRef; | |
}, | |
empty: (templateRef: TemplateRef<unknown>) => { | |
this.emptyTemplate = templateRef; | |
} | |
}; | |
setTemplate(name: string, template: TemplateRef<unknown>) { | |
if (!!this.templateNameSetters[name]) { | |
this.templateNameSetters[name](template); | |
} else { | |
// Optional, Throwing an error can cause usability difficulties in some cases. | |
throw new Error(`'${name}' template is not supported by '${MyAlternateListComponent.name}'`); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Directive, Inject, Input, TemplateRef } from "@angular/core"; | |
import { APP_TEMPLATE_CONSUMER_ACCESSOR, TemplateConsumer } from "./models/TemplateConsumer"; | |
@Directive({ | |
selector: '[appTemplate]' | |
}) | |
export class TemplateDirective { | |
constructor( | |
// Injecting the component instance that provides APP_TEMPLATE_CONSUMER_ACCESSOR | |
@Inject(APP_TEMPLATE_CONSUMER_ACCESSOR) private readonly templateConsumer: TemplateConsumer, | |
private readonly templateRef: TemplateRef<unknown> | |
) { } | |
private _appTemplate: string; | |
@Input() | |
set appTemplate(value: string) { | |
this._appTemplate = value; | |
this.templateConsumer.setTemplate(value, this.templateRef); | |
} | |
get appTemplate(): string { | |
return this._appTemplate; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { InjectionToken, TemplateRef } from "@angular/core"; | |
export interface TemplateConsumer{ | |
setTemplate(name: string, template: TemplateRef<unknown>); | |
} | |
export const APP_TEMPLATE_CONSUMER_ACCESSOR = | |
new InjectionToken<ReadonlyArray<TemplateConsumer>>('TemplateConsumerAccessor'); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment