diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/en.json b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/en.json index 8ce00a7c5b..29035fb57f 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/en.json +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/en.json @@ -24,6 +24,8 @@ "ThisFieldMustBeAStringOrArrayTypeWithAMinimumLengthOf{0}": "This field must be a string or array type with a minimum length of '{0}'.", "ThisFieldIsNotAValidPhoneNumber.": "This field is not a valid phone number.", "ThisFieldMustBeBetween{0}And{1}": "This field must be between {0} and {1}.", + "ThisFieldMustBeGreaterThanOrEqual{0}":"This field must be greater than or equal to {0}.", + "ThisFieldMustBeLessOrEqual{0}":"This field must be less than or equal to {0}.", "ThisFieldMustMatchTheRegularExpression{0}": "This field must match the regular expression '{0}'.", "ThisFieldIsRequired.": "This field is required.", "ThisFieldMustBeAStringWithAMaximumLengthOf{0}": "This field must be a string with a maximum length of {0}.", 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(() => {}); diff --git a/npm/ng-packs/packages/theme-shared/src/lib/constants/validation.ts b/npm/ng-packs/packages/theme-shared/src/lib/constants/validation.ts index 65b759a21e..33c6e1741c 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/constants/validation.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/constants/validation.ts @@ -2,10 +2,10 @@ export const DEFAULT_VALIDATION_BLUEPRINTS = { creditCard: 'AbpValidation::ThisFieldIsNotAValidCreditCardNumber.', email: 'AbpValidation::ThisFieldIsNotAValidEmailAddress.', invalid: 'AbpValidation::ThisFieldIsNotValid.', - max: 'AbpValidation::ThisFieldMustBeBetween{0}And{1}[{{ min }},{{ max }}]', + max: 'AbpValidation::ThisFieldMustBeLessOrEqual{0}[{{ max }}]', maxlength: 'AbpValidation::ThisFieldMustBeAStringOrArrayTypeWithAMaximumLengthOf{0}[{{ requiredLength }}]', - min: 'AbpValidation::ThisFieldMustBeBetween{0}And{1}[{{ min }},{{ max }}]', + min: 'AbpValidation::ThisFieldMustBeGreaterThanOrEqual{0}[{{ min }}]', minlength: 'AbpValidation::ThisFieldMustBeAStringOrArrayTypeWithAMinimumLengthOf{0}[{{ requiredLength }}]', ngbDate: 'AbpValidation::ThisFieldIsNotValid.',