From 3db32de0f5175578eb1013d9db9e55d87737b04e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Muhammed=20Altu=C4=9F?= Date: Thu, 14 Jul 2022 10:52:22 +0300 Subject: [PATCH] fix range error in permission directive (#13307) --- .../lib/directives/permission.directive.ts | 22 +++++++++++++++---- .../lib/tests/permission.directive.spec.ts | 14 ++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts b/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts index 824b013843..a103b11a46 100644 --- a/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts +++ b/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts @@ -1,4 +1,5 @@ import { + AfterViewInit, ChangeDetectorRef, Directive, Input, @@ -8,20 +9,24 @@ import { TemplateRef, ViewContainerRef, } from '@angular/core'; -import { Subscription } from 'rxjs'; -import { distinctUntilChanged } from 'rxjs/operators'; +import { ReplaySubject, Subscription } from 'rxjs'; +import { distinctUntilChanged, take } from 'rxjs/operators'; import { PermissionService } from '../services/permission.service'; @Directive({ selector: '[abpPermission]', }) -export class PermissionDirective implements OnDestroy, OnChanges { +export class PermissionDirective implements OnDestroy, OnChanges, AfterViewInit { @Input('abpPermission') condition: string | undefined; @Input('abpPermissionRunChangeDetection') runChangeDetection = true; subscription!: Subscription; + cdrSubject = new ReplaySubject(); + + rendered = false; + constructor( @Optional() private templateRef: TemplateRef, private vcRef: ViewContainerRef, @@ -41,7 +46,11 @@ export class PermissionDirective implements OnDestroy, OnChanges { this.vcRef.clear(); if (isGranted) this.vcRef.createEmbeddedView(this.templateRef); if (this.runChangeDetection) { - this.cdRef.detectChanges(); + if (!this.rendered) { + this.cdrSubject.next(); + } else { + this.cdRef.detectChanges(); + } } else { this.cdRef.markForCheck(); } @@ -55,4 +64,9 @@ export class PermissionDirective implements OnDestroy, OnChanges { ngOnChanges() { this.check(); } + + ngAfterViewInit() { + this.cdrSubject.pipe(take(1)).subscribe(() => this.cdRef.detectChanges()); + this.rendered = true; + } } diff --git a/npm/ng-packs/packages/core/src/lib/tests/permission.directive.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/permission.directive.spec.ts index 37d792787c..4e64e61da8 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/permission.directive.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/permission.directive.spec.ts @@ -76,6 +76,20 @@ describe('PermissionDirective', () => { expect(detectChanges).toHaveBeenCalled(); }); + it('should not call change detection before ngAfterViewInit', () => { + // hook before ngAfterViewInit + + const detectChanges = jest.spyOn(cdr, 'detectChanges'); + spectator.setHostInput({ condition: 'test' }); + grantedPolicy$.next(true); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + directive.onInit = () => { + expect(detectChanges).not.toHaveBeenCalled(); + }; + expect(detectChanges).toHaveBeenCalled(); + }); + describe('#subscription', () => { it('should call the unsubscribe', () => { const spy = jest.fn(() => {});