Browse Source

Merge pull request #13147 from abpframework/fix/extensible-table-range-error

do not run change detection in extensible system components
pull/13155/head
Mahmut Gundogdu 4 years ago
committed by GitHub
parent
commit
6fdc8ac66f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      npm/ng-packs/packages/core/src/lib/core.module.ts
  2. 8
      npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts
  3. 50
      npm/ng-packs/packages/core/src/lib/tests/permission.directive.spec.ts
  4. 6
      npm/ng-packs/packages/theme-shared/extensions/src/lib/components/extensible-form/extensible-form-prop.component.html
  5. 2
      npm/ng-packs/packages/theme-shared/extensions/src/lib/components/extensible-table/extensible-table.component.html
  6. 4
      npm/ng-packs/packages/theme-shared/extensions/src/lib/components/grid-actions/grid-actions.component.html
  7. 8
      npm/ng-packs/packages/theme-shared/extensions/src/lib/components/page-toolbar/page-toolbar.component.html

2
npm/ng-packs/packages/core/src/lib/core.module.ts

@ -136,6 +136,7 @@ export class CoreModule {
return {
ngModule: RootCoreModule,
providers: [
OAuthModule.forRoot().providers,
LocaleProvider,
CookieLanguageProvider,
{
@ -190,7 +191,6 @@ export class CoreModule {
useValue: localizationContributor(options.localizations),
deps: [LocalizationService],
},
OAuthModule.forRoot().providers,
],
};
}

8
npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts

@ -18,6 +18,8 @@ import { PermissionService } from '../services/permission.service';
export class PermissionDirective implements OnDestroy, OnChanges {
@Input('abpPermission') condition: string | undefined;
@Input('abpPermissionRunChangeDetection') runChangeDetection = true;
subscription!: Subscription;
constructor(
@ -38,7 +40,11 @@ export class PermissionDirective implements OnDestroy, OnChanges {
.subscribe(isGranted => {
this.vcRef.clear();
if (isGranted) this.vcRef.createEmbeddedView(this.templateRef);
this.cdRef.detectChanges();
if (this.runChangeDetection) {
this.cdRef.detectChanges();
} else {
this.cdRef.markForCheck();
}
});
}

50
npm/ng-packs/packages/core/src/lib/tests/permission.directive.spec.ts

@ -2,10 +2,12 @@ import { createDirectiveFactory, SpectatorDirective } from '@ngneat/spectator/je
import { Subject } from 'rxjs';
import { PermissionDirective } from '../directives/permission.directive';
import { PermissionService } from '../services';
import { ChangeDetectorRef } from '@angular/core';
describe('PermissionDirective', () => {
let spectator: SpectatorDirective<PermissionDirective>;
let directive: PermissionDirective;
let cdr: ChangeDetectorRef;
const grantedPolicy$ = new Subject<boolean>();
const createDirective = createDirectiveFactory({
directive: PermissionDirective,
@ -30,7 +32,7 @@ describe('PermissionDirective', () => {
grantedPolicy$.next(true);
expect(spectator.query('#test-element')).toBeTruthy();
grantedPolicy$.next(false);
// expect(spectator.query('#test-element')).toBeFalsy(); // TODO: change detection problem should be fixed
expect(spectator.query('#test-element')).toBeFalsy();
});
});
@ -41,6 +43,7 @@ describe('PermissionDirective', () => {
{ hostProps: { condition: '' } },
);
directive = spectator.directive;
cdr = (directive as any).cdRef as ChangeDetectorRef;
});
it('should be created', () => {
@ -55,8 +58,22 @@ describe('PermissionDirective', () => {
grantedPolicy$.next(false);
expect(spectator.query('#test-element')).toBeFalsy();
grantedPolicy$.next(true);
expect(spectator.queryAll('#test-element')).toHaveLength(1);
});
it('should call detect changes method', () => {
const detectChanges = jest.spyOn(cdr, 'detectChanges');
expect(spectator.query('#test-element')).toBeFalsy();
spectator.setHostInput({ condition: 'test' });
grantedPolicy$.next(true);
expect(spectator.query('#test-element')).toBeTruthy();
expect(detectChanges).toHaveBeenCalled();
grantedPolicy$.next(false);
expect(spectator.query('#test-element')).toBeFalsy();
expect(detectChanges).toHaveBeenCalled();
grantedPolicy$.next(true);
expect(spectator.queryAll('#test-element')).toHaveLength(1);
expect(detectChanges).toHaveBeenCalled();
});
describe('#subscription', () => {
@ -70,4 +87,35 @@ describe('PermissionDirective', () => {
});
});
});
describe('with runChangeDetection Input', () => {
beforeEach(() => {
spectator = createDirective(
'<div id="test-element" *abpPermission="condition;runChangeDetection:false">Testing Permission Directive</div>',
{ hostProps: { condition: '' } },
);
directive = spectator.directive;
cdr = (directive as any).cdRef as ChangeDetectorRef;
});
it('should not call detectChanges method', () => {
const detectChanges = jest.spyOn(cdr, 'detectChanges');
const markForCheck = jest.spyOn(cdr, 'markForCheck');
expect(spectator.query('#test-element')).toBeFalsy();
spectator.setHostInput({ condition: 'test' });
grantedPolicy$.next(true);
expect(spectator.query('#test-element')).toBeTruthy();
expect(detectChanges).not.toHaveBeenCalled();
expect(markForCheck).toHaveBeenCalled();
grantedPolicy$.next(false);
expect(spectator.query('#test-element')).toBeFalsy();
expect(detectChanges).not.toHaveBeenCalled();
expect(markForCheck).toHaveBeenCalled();
grantedPolicy$.next(true);
expect(spectator.queryAll('#test-element')).toHaveLength(1);
expect(detectChanges).not.toHaveBeenCalled();
expect(markForCheck).toHaveBeenCalled();
});
});
});

6
npm/ng-packs/packages/theme-shared/extensions/src/lib/components/extensible-form/extensible-form-prop.component.html

@ -1,4 +1,8 @@
<div class="mb-3 form-group" *abpPermission="prop.permission" [ngSwitch]="getComponent(prop)">
<div
class="mb-3 form-group"
*abpPermission="prop.permission; runChangeDetection: false"
[ngSwitch]="getComponent(prop)"
>
<ng-template ngSwitchCase="input">
<ng-template [ngTemplateOutlet]="label"></ng-template>
<input

2
npm/ng-packs/packages/theme-shared/extensions/src/lib/components/extensible-table/extensible-table.component.html

@ -24,7 +24,7 @@
[sortable]="prop.sortable"
>
<ng-template let-row="row" let-i="index" ngx-datatable-cell-template>
<ng-container *abpPermission="prop.permission">
<ng-container *abpPermission="prop.permission; runChangeDetection: false">
<ng-container *ngIf="row['_' + prop.name]?.visible">
<div
*ngIf="!row['_' + prop.name].component; else component"

4
npm/ng-packs/packages/theme-shared/extensions/src/lib/components/grid-actions/grid-actions.component.html

@ -27,7 +27,7 @@
<ng-container *ngIf="action.visible(data)">
<button
ngbDropdownItem
*abpPermission="action.permission"
*abpPermission="action.permission; runChangeDetection: false"
(click)="action.action(data)"
type="button"
>
@ -49,7 +49,7 @@
<ng-template #btnTmp let-action>
<ng-container *ngIf="action.visible(data)">
<button
*abpPermission="action.permission"
*abpPermission="action.permission; runChangeDetection: false"
(click)="action.action(data)"
type="button"
class="btn btn-primary text-center"

8
npm/ng-packs/packages/theme-shared/extensions/src/lib/components/page-toolbar/page-toolbar.component.html

@ -5,7 +5,7 @@
*ngFor="let action of actionList; trackBy: trackByFn; let last = last"
>
<ng-container *ngIf="action.visible(data)">
<ng-container *abpPermission="action.permission">
<ng-container *abpPermission="action.permission;runChangeDetection: false">
<ng-container *ngIf="action.component as component; else button">
<ng-container
*ngComponentOutlet="component; injector: record | createInjector: action:this"
@ -13,7 +13,11 @@
</ng-container>
<ng-template #button>
<button (click)="action.action(data)" type="button" [ngClass]="action.btnClass ? action.btnClass : defaultBtnClass" >
<button
(click)="action.action(data)"
type="button"
[ngClass]="action.btnClass ? action.btnClass : defaultBtnClass"
>
<i [ngClass]="action.icon" [class.me-1]="action.icon"></i>
{{ action.text | abpLocalization }}
</button>

Loading…
Cancel
Save