Skip to content

Instantly share code, notes, and snippets.

@vmasek
Last active July 24, 2019 18:21
Show Gist options
  • Save vmasek/db5132a7f0ffa5022e92cbe738ec47b7 to your computer and use it in GitHub Desktop.
Save vmasek/db5132a7f0ffa5022e92cbe738ec47b7 to your computer and use it in GitHub Desktop.
Structural directives - Let directive
/**
* This interface represents context of the directive.
*
* It defines two properties ($implicit and appLet) which enables same behavior with different syntax.
* It is not required to have both, it is just a way to provide support for both syntax.
*/
interface LetContext<T> {
/**
* Current item exposed in implicit value variable.
* This enables us to use the let syntax
*
* @example
* <ng-container *appLet="data$ | async; let data">
* Data: {{data}}
* </ng-container>
*/
$implicit?: T; // current item exposed as implicit value
/**
* Current item exposed as key matching the directive name.
* This adds support for `as` syntax in template.
*
* @example
* <ng-container *appLet="data$ | async as data">
* Data: {{data}}
* </ng-container>
*/
appLet?: T;
}
@Directive({
selector: '[appLet]'
})
export class LetDirective<T> {
private context: LetContext<T> = {
$implicit: undefined,
appLet: undefined
};
constructor(private readonly viewRef: ViewContainerRef,
private readonly templateRef: TemplateRef<LetContext<T>>) {
this.viewRef.createEmbeddedView(this.templateRef, this.context);
}
@Input()
set appLet(value: T) {
this.context.appLet = this.context.$implicit = value;
}
}
<ng-container *appLet="data$ | async as data;"> <!-- single subscription -->
<div>
Data: {{data}} <!-- false -->
</div>
</ng-container>
<ng-container *appLet="data$ | async; let data2"> <!-- single subscription -->
<div>
Data2: {{data2}} <!-- same value as Data (false) -->
</div>
</ng-container>
@vmasek
Copy link
Author

vmasek commented Jul 24, 2019

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