diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.html b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.html index 3484c452a0..8dab9ea8fd 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.html +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.html @@ -32,7 +32,7 @@ [class.d-block]="smallScreen && currentUserDropdown.isOpen()" > - + - + \ No newline at end of file diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/index.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/index.ts index b0a79877fe..3f22a36f1b 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/directives/index.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/index.ts @@ -2,3 +2,4 @@ export * from './ellipsis.directive'; export * from './loading.directive'; export * from './ngx-datatable-default.directive'; export * from './ngx-datatable-list.directive'; +export * from './visible.directive'; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/visible.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/visible.directive.ts new file mode 100644 index 0000000000..9c2c408d0e --- /dev/null +++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/visible.directive.ts @@ -0,0 +1,59 @@ +import { OnInit, Directive, OnDestroy, Input, ViewContainerRef, TemplateRef } from '@angular/core'; +import { EMPTY, from, Observable, of, Subscription } from 'rxjs'; + +@Directive({ + selector: '[abpVisible]', +}) +export class AbpVisibleDirective implements OnDestroy, OnInit { + conditionSubscription: Subscription | undefined; + isVisible: boolean | undefined; + + @Input('abpVisible') set abpVisible( + value: boolean | Promise | Observable | undefined | null, + ) { + this.condition$ = checkType(value); + this.subscribeToCondition(); + } + + private condition$: Observable = of(false); + + constructor( + private viewContainerRef: ViewContainerRef, + private templateRef: TemplateRef, + ) {} + ngOnInit(): void { + this.updateVisibility(); + } + ngOnDestroy(): void { + this.conditionSubscription?.unsubscribe(); + } + + private subscribeToCondition() { + this.conditionSubscription = this.condition$.subscribe(value => { + this.isVisible = value; + this.updateVisibility(); + }); + } + private updateVisibility() { + this.viewContainerRef.clear(); + // it should be false not falsy + if (this.isVisible === false) { + return; + } + this.viewContainerRef.createEmbeddedView(this.templateRef); + } +} + +function checkType(value: boolean | Promise | Observable | undefined | null) { + if (value instanceof Promise) { + return from(value); + } else if (value instanceof Observable) { + return value; + } else if (typeof value === 'boolean') { + return of(value); + } else if (value === undefined || value === null) { + return of(true); + } else { + return EMPTY; + } +} diff --git a/npm/ng-packs/packages/theme-shared/src/lib/models/nav-item.ts b/npm/ng-packs/packages/theme-shared/src/lib/models/nav-item.ts index 62ccf32ff3..706eb1cb6c 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/models/nav-item.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/models/nav-item.ts @@ -1,4 +1,5 @@ -import { Type } from '@angular/core'; +import { Injector, Type } from '@angular/core'; +import { Observable, of } from 'rxjs'; export class NavItem { id?: string | number; @@ -7,9 +8,13 @@ export class NavItem { action?: () => void; order?: number; requiredPolicy?: string; - visible?: () => boolean; + visible?: NavBarPropPredicate; constructor(props: Partial) { - props = { ...props, visible: props.visible || (() => true) }; Object.assign(this, props); } } + +export type NavBarPropPredicate = ( + prop?: T, + injector?: Injector, +) => boolean | Promise | Observable; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts b/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts index fd9a0cd236..20c7de13d4 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts @@ -36,6 +36,7 @@ import { HTTP_ERROR_CONFIG, httpErrorConfigFactory } from './tokens/http-error.t import { DateParserFormatter } from './utils/date-parser-formatter'; import { CONFIRMATION_ICONS, DEFAULT_CONFIRMATION_ICONS } from './tokens/confirmation-icons.token'; import { PasswordComponent } from './components/password/password.component'; +import { AbpVisibleDirective } from './directives'; const declarationsWithExports = [ BreadcrumbComponent, @@ -52,6 +53,7 @@ const declarationsWithExports = [ NgxDatatableListDirective, LoadingDirective, ModalCloseDirective, + AbpVisibleDirective, ]; @NgModule({