Skip to content

Commit

Permalink
Enhance ngIf augmentation directive with optional empty array handlin…
Browse files Browse the repository at this point in the history
…g as empty (#80)

* Enhance ngIf augmentation directive with optional empty array handling as empty.

* Fix lint error.

---------

Co-authored-by: Zsolt Novak <zsolt.novak@massivedynamics.hu>
  • Loading branch information
torposz and Zsolt Novak committed May 16, 2024
1 parent a612bd0 commit d1c23a3
Showing 1 changed file with 42 additions and 8 deletions.
50 changes: 42 additions & 8 deletions libs/ng-utils/src/lib/directives/ng-if-augmentation.directive.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
/* eslint-disable @angular-eslint/directive-selector */
import { NgIf, NgIfContext } from '@angular/common';
import { HttpErrorResponse } from '@angular/common/http';
import { Directive, Host, Input, OnChanges, TemplateRef } from '@angular/core';

/**
* A utility directive that enhances Angular's *ngIf directive with extra functionality.
* The directive is implicitly applied every time the original *ngIf is used and provides two additional template options for *ngIF.
* You can supply both a loading and error template for *ngIf.
* This can be particularly useful when you are working with async data
* This can be particularly useful when you are working with async data.
* While the value is null shows loading template if provided. (async pipe default value is null)
* @example ```html
* <p *ngIf="value$ | async as value else default or loading but error">
* <p *ngIf="value$ | async as value; else default; or loading; but error">
* {{value}}
* </p>
* ```
* This shows the else template if value is an empty array
* @example ```html
* <p *ngIf="value$ | async as value; else empty; or: loading; but: error; empty: true">
* {{value}}
* </p>
* ```
*
* @credit
* Alexander Inkin - https://medium.com/@waterplea
*
Expand All @@ -21,6 +30,7 @@ import { Directive, Host, Input, OnChanges, TemplateRef } from '@angular/core';
selector: '[ngIf][ngIfOr],[ngIf][ngIfBut]',
})
export class NgIfAugmentedDirective<T> implements OnChanges {

/**
* Keeping track of the value
*/
Expand Down Expand Up @@ -51,37 +61,61 @@ export class NgIfAugmentedDirective<T> implements OnChanges {
@Input()
public ngIfBut: TemplateRef<NgIfContext<T>> | null = null;

/**
* Empty array shows else template, default false.
* This is because the original ngIf shows the ngIfThen template when the value is empty array.
*/
@Input()
public ngIfEmpty = false;

/**
* @param directive The original ngIf directive instance on this host element
* @param templateRef The template encapsulated by the directive.
*/
constructor(
@Host() private readonly directive: NgIf<T>,
private readonly templateRef: TemplateRef<NgIfContext<T>>
) {}
) {
}

/**
* @ignore
*/
public ngOnChanges(): void {
if (!this.ngIf && this.ngIfOr) {

// Loading
if (this.ngIf === null && this.ngIfOr) {
this.directive.ngIfElse = this.ngIfOr;

return;
}

if (this.ngIf instanceof Error && this.ngIfBut) {
// Error
if (this.ngIfBut && ((this.ngIf instanceof Error) || (this.ngIf instanceof HttpErrorResponse))) {
this.directive.ngIfThen = this.ngIfBut;

return;
}

if (this.directive.ngIfThen !== this.ngIfThen) {
this.directive.ngIfThen = this.ngIfThen;
// Empty array
if (this.ngIfEmpty && (Array.isArray(this.ngIf) && this.ngIf.length === 0) && this.directive.ngIfThen !== this.ngIfElse) {
this.directive.ngIfThen = this.ngIfElse;

return;
}

if (this.directive.ngIfElse !== this.ngIfElse) {
// Empty
if (!!this.ngIf === false && this.directive.ngIfElse !== this.ngIfElse) {
this.directive.ngIfElse = this.ngIfElse;

return;
}

// Normal
if (!!this.ngIf === true && this.directive.ngIfThen !== this.ngIfThen) {
this.directive.ngIfThen = this.ngIfThen;

return;
}
}
}

0 comments on commit d1c23a3

Please sign in to comment.