diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/jquery/jquery-extensions.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/jquery/jquery-extensions.js index b3fa839d10..44c2bdad27 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/jquery/jquery-extensions.js +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/jquery/jquery-extensions.js @@ -160,7 +160,7 @@ formSaved = true; $modal.modal('hide'); } - }); + }, false); } }); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert/abp-sweetalert.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert/abp-sweetalert.js index c96f836f0d..0ed8460966 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert/abp-sweetalert.js +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert/abp-sweetalert.js @@ -73,17 +73,21 @@ return showMessage('error', message, title); }; - abp.message.confirm = function (message, titleOrCallback, callback) { + abp.message.confirm = function (message, titleOrCallback, callback, closeOnEsc) { + var userOpts = { text: message }; if ($.isFunction(titleOrCallback)) { + closeOnEsc = callback; callback = titleOrCallback; } else if (titleOrCallback) { userOpts.title = titleOrCallback; }; + userOpts.closeOnEsc = closeOnEsc; + var opts = $.extend( {}, abp.libs.sweetAlert.config['default'], diff --git a/npm/ng-packs/packages/core/src/lib/core.module.ts b/npm/ng-packs/packages/core/src/lib/core.module.ts index 9e822a4823..4b657fe8bb 100644 --- a/npm/ng-packs/packages/core/src/lib/core.module.ts +++ b/npm/ng-packs/packages/core/src/lib/core.module.ts @@ -20,6 +20,8 @@ import { SessionState } from './states/session.state'; import { getInitialData } from './utils/initial-utils'; import { EllipsisDirective } from './directives/ellipsis.directive'; import { AutofocusDirective } from './directives/autofocus.directive'; +import { InputEventDebounceDirective } from './directives/debounce.directive'; +import { ClickEventStopPropagationDirective } from './directives/stop-propagation.directive'; @NgModule({ imports: [ @@ -40,6 +42,8 @@ import { AutofocusDirective } from './directives/autofocus.directive'; LocalizationPipe, PermissionDirective, VisibilityDirective, + InputEventDebounceDirective, + ClickEventStopPropagationDirective, ], exports: [ CommonModule, @@ -54,7 +58,9 @@ import { AutofocusDirective } from './directives/autofocus.directive'; LocalizationPipe, PermissionDirective, VisibilityDirective, + InputEventDebounceDirective, LocalizationPipe, + ClickEventStopPropagationDirective, ], providers: [LocalizationPipe], entryComponents: [RouterOutletComponent, DynamicLayoutComponent], diff --git a/npm/ng-packs/packages/core/src/lib/directives/debounce.directive.ts b/npm/ng-packs/packages/core/src/lib/directives/debounce.directive.ts new file mode 100644 index 0000000000..144c43d4e2 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/directives/debounce.directive.ts @@ -0,0 +1,26 @@ +import { Directive, Output, Renderer2, ElementRef, OnInit, EventEmitter, Input } from '@angular/core'; +import { fromEvent } from 'rxjs'; +import { debounceTime } from 'rxjs/operators'; +import { takeUntilDestroy } from '@ngx-validate/core'; + +@Directive({ + selector: '[input.debounce]', +}) +export class InputEventDebounceDirective implements OnInit { + @Input() debounce: number = 300; + + @Output('input.debounce') debounceEvent = new EventEmitter(); + + constructor(private renderer: Renderer2, private el: ElementRef) {} + + ngOnInit(): void { + fromEvent(this.el.nativeElement, 'input') + .pipe( + debounceTime(this.debounce), + takeUntilDestroy(this), + ) + .subscribe((event: Event) => { + this.debounceEvent.emit(event); + }); + } +} diff --git a/npm/ng-packs/packages/core/src/lib/directives/stop-propagation.directive.ts b/npm/ng-packs/packages/core/src/lib/directives/stop-propagation.directive.ts new file mode 100644 index 0000000000..ffa2e9e10b --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/directives/stop-propagation.directive.ts @@ -0,0 +1,21 @@ +import { Directive, ElementRef, EventEmitter, OnInit, Output, Renderer2 } from '@angular/core'; +import { fromEvent } from 'rxjs'; +import { takeUntilDestroy } from '@ngx-validate/core'; + +@Directive({ + selector: '[click.stop]', +}) +export class ClickEventStopPropagationDirective implements OnInit { + @Output('click.stop') stopPropEvent = new EventEmitter(); + + constructor(private renderer: Renderer2, private el: ElementRef) {} + + ngOnInit(): void { + fromEvent(this.el.nativeElement, 'click') + .pipe(takeUntilDestroy(this)) + .subscribe((event: MouseEvent) => { + event.stopPropagation(); + this.stopPropEvent.emit(event); + }); + } +} diff --git a/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html b/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html index af162133da..546a768006 100644 --- a/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html +++ b/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html @@ -18,7 +18,7 @@ type="search" class="form-control form-control-sm" [placeholder]="'AbpUi::PagerSearch' | abpLocalization" - (input)="search$.next($event.target.value)" + (input.debounce)="onSearch($event.target.value)" /> ; @@ -42,18 +42,14 @@ export class RolesComponent implements OnInit { loading: boolean = false; - search$ = new Subject(); - @ViewChild('modalContent', { static: false }) modalContent: TemplateRef; constructor(private confirmationService: ConfirmationService, private fb: FormBuilder, private store: Store) {} - ngOnInit() { - this.search$.pipe(debounceTime(300)).subscribe(value => { - this.pageQuery.filter = value; - this.get(); - }); + onSearch(value) { + this.pageQuery.filter = value; + this.get(); } createForm() { diff --git a/npm/ng-packs/packages/identity/src/lib/components/users/users.component.html b/npm/ng-packs/packages/identity/src/lib/components/users/users.component.html index 9d5aa0a9f0..03f5dcb605 100644 --- a/npm/ng-packs/packages/identity/src/lib/components/users/users.component.html +++ b/npm/ng-packs/packages/identity/src/lib/components/users/users.component.html @@ -24,7 +24,7 @@ type="search" class="form-control form-control-sm" [placeholder]="'AbpUi::PagerSearch' | abpLocalization" - (input)="search$.next($event.target.value)" + (input.debounce)="onSearch($event.target.value)" /> ; @@ -50,8 +50,6 @@ export class UsersComponent implements OnInit { loading: boolean = false; - search$ = new Subject(); - trackByFn: TrackByFunction = (index, item) => Object.keys(item)[0] || index; get roleGroups(): FormGroup[] { @@ -60,11 +58,9 @@ export class UsersComponent implements OnInit { constructor(private confirmationService: ConfirmationService, private fb: FormBuilder, private store: Store) {} - ngOnInit() { - this.search$.pipe(debounceTime(300)).subscribe(value => { - this.pageQuery.filter = value; - this.get(); - }); + onSearch(value) { + this.pageQuery.filter = value; + this.get(); } buildForm() { diff --git a/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html b/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html index ec059131e0..b8c206a74d 100644 --- a/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html +++ b/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html @@ -27,7 +27,7 @@ type="search" class="form-control form-control-sm" [placeholder]="'AbpUi::PagerSearch' | abpLocalization" - (input)="search$.next($event.target.value)" + (input.debounce)="onSearch($event.target.value)" /> ; @@ -52,8 +52,6 @@ export class TenantsComponent implements OnInit { loading: boolean = false; - search$ = new Subject(); - get useSharedDatabase(): boolean { return this.defaultConnectionStringForm.get('useSharedDatabase').value; } @@ -75,11 +73,9 @@ export class TenantsComponent implements OnInit { private store: Store, ) {} - ngOnInit() { - this.search$.pipe(debounceTime(300)).subscribe(value => { - this.pageQuery.filter = value; - this.get(); - }); + onSearch(value) { + this.pageQuery.filter = value; + this.get(); } private createTenantForm() { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.html b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.html index 8db9f31cb7..559bc6b429 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.html +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.html @@ -1,5 +1,6 @@