Steal this elegant trick right now to repeat templates without *ngFor
The *ngFor
directive is great when repeating templates for iterables. But when it comes to simply repeating templates based on a number, you have to hack your way around it.
Wouldnβt it be cool to be able to do something like this?
<div *repeatTimes="length; index as i">
{{ i }} This will render {{ length }} times
</div>
Well, we can π
Letβs write a structural directive to make the magic happen:
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
export type RepeatTimesContext = {
$implicit: number;
index: number;
}
@Directive({
selector: '[repeatTimes]'
})
export class RepeatTimesDirective {
static ngTemplateContextGuard(
dir: RepeatTimesDirective, ctx: unknown
): ctx is RepeatTimesContext { return true; };
constructor (
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef
) { }
@Input('repeatTimes') set count(count: number) {
this.viewContainer.clear();
for (let i = 0; i < count; i++) {
this.viewContainer.createEmbeddedView<RepeatTimesContext>(this.templateRef, { $implicit: i, index: i });
}
}
}
This neat little directive supports 2 micro syntaxes for you to choose as per your liking.
<div *repeatTimes="length; index as i">
{{ i }} This will render {{ length }} times
</div>
<!-- Or -->
<div *repeat="let index times length;">
{{ index }} This will render {{ length }} times
</div>
It is also available for you to use on npm ngx-repeat-times
You can check out its usage in this StackBlitz below
Feel free to reach out and let me know how it works for you ;)
Happy Engineering!