From 956773d7c3a6130ca7cd5d4c7f0f55784113f696 Mon Sep 17 00:00:00 2001 From: Fahri Gedik <53567152+fahrigedik@users.noreply.github.com> Date: Wed, 28 Jan 2026 15:27:28 +0300 Subject: [PATCH 1/3] Refactor to use Angular's new output() event API Replaces all usages of EventEmitter and @Output with the new output() API across multiple components and directives. This modernizes event handling to align with Angular's latest best practices and improves code consistency. --- .../extensible-table.component.ts | 11 +++++----- .../src/lib/directives/caps-lock.directive.ts | 4 ++-- .../src/lib/directives/debounce.directive.ts | 4 ++-- .../lib/directives/form-submit.directive.ts | 19 ++++++++--------- .../core/src/lib/directives/init.directive.ts | 4 ++-- .../directives/stop-propagation.directive.ts | 4 ++-- .../feature-management.component.ts | 4 ++-- .../permission-management.component.ts | 5 ++--- .../lib/components/button/button.component.ts | 21 +++++++++---------- .../components/checkbox/checkbox.component.ts | 10 ++++----- .../form-input/form-input.component.ts | 10 ++++----- .../lib/components/toast/toast.component.ts | 4 ++-- 12 files changed, 48 insertions(+), 52 deletions(-) diff --git a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts index 75253b1f02..a245517282 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts +++ b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts @@ -5,20 +5,19 @@ import { Component, computed, ContentChild, - EventEmitter, inject, Injector, Input, LOCALE_ID, OnChanges, OnDestroy, - Output, PLATFORM_ID, signal, SimpleChanges, TemplateRef, TrackByFunction, ViewChild, + output } from '@angular/core'; import { AsyncPipe, isPlatformBrowser, NgComponentOutlet, NgTemplateOutlet } from '@angular/common'; @@ -118,7 +117,7 @@ export class ExtensibleTableComponent implements OnChanges, AfterViewIn @Input() actionsTemplate?: TemplateRef; - @Output() tableActivate = new EventEmitter(); + readonly tableActivate = output(); @Input() selectable = false; @@ -128,18 +127,18 @@ export class ExtensibleTableComponent implements OnChanges, AfterViewIn _selectionType: SelectionType = SelectionType.multiClick; @Input() selected: any[] = []; - @Output() selectionChange = new EventEmitter(); + readonly selectionChange = output(); // Infinite scroll configuration @Input() infiniteScroll = false; @Input() isLoading = false; @Input() scrollThreshold = 10; - @Output() loadMore = new EventEmitter(); + readonly loadMore = output(); @Input() tableHeight: number; @Input() rowDetailTemplate?: TemplateRef>; @Input() rowDetailHeight: string | number = '100%'; - @Output() rowDetailToggle = new EventEmitter(); + readonly rowDetailToggle = output(); @ContentChild(ExtensibleTableRowDetailComponent) rowDetailComponent?: ExtensibleTableRowDetailComponent; diff --git a/npm/ng-packs/packages/core/src/lib/directives/caps-lock.directive.ts b/npm/ng-packs/packages/core/src/lib/directives/caps-lock.directive.ts index 99bfcebb92..792b671962 100644 --- a/npm/ng-packs/packages/core/src/lib/directives/caps-lock.directive.ts +++ b/npm/ng-packs/packages/core/src/lib/directives/caps-lock.directive.ts @@ -1,10 +1,10 @@ -import { Directive, EventEmitter, HostListener, Output } from '@angular/core'; +import { Directive, HostListener, output } from '@angular/core'; @Directive({ selector: '[abpCapsLock]', }) export class TrackCapsLockDirective { - @Output('abpCapsLock') capsLock = new EventEmitter(); + readonly capsLock = output({ alias: 'abpCapsLock' }); @HostListener('window:keydown', ['$event']) onKeyDown(event: KeyboardEvent): void { 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 index 239aed688d..a3fb542d4d 100644 --- a/npm/ng-packs/packages/core/src/lib/directives/debounce.directive.ts +++ b/npm/ng-packs/packages/core/src/lib/directives/debounce.directive.ts @@ -1,4 +1,4 @@ -import { Directive, ElementRef, EventEmitter, Input, OnInit, Output, inject } from '@angular/core'; +import { Directive, ElementRef, Input, OnInit, inject, output } from '@angular/core'; import { fromEvent } from 'rxjs'; import { debounceTime } from 'rxjs/operators'; import { SubscriptionService } from '../services/subscription.service'; @@ -13,7 +13,7 @@ export class InputEventDebounceDirective implements OnInit { @Input() debounce = 300; - @Output('input.debounce') readonly debounceEvent = new EventEmitter(); + readonly debounceEvent = output({ alias: 'input.debounce' }); ngOnInit(): void { const input$ = fromEvent(this.el.nativeElement, 'input').pipe( diff --git a/npm/ng-packs/packages/core/src/lib/directives/form-submit.directive.ts b/npm/ng-packs/packages/core/src/lib/directives/form-submit.directive.ts index 879fbdf780..eaeca51e94 100644 --- a/npm/ng-packs/packages/core/src/lib/directives/form-submit.directive.ts +++ b/npm/ng-packs/packages/core/src/lib/directives/form-submit.directive.ts @@ -1,12 +1,11 @@ -import { - ChangeDetectorRef, - Directive, - ElementRef, - EventEmitter, - Input, - OnInit, - Output, - inject +import { + ChangeDetectorRef, + Directive, + ElementRef, + Input, + OnInit, + inject, + output } from '@angular/core'; import { FormGroupDirective, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; import { fromEvent } from 'rxjs'; @@ -37,7 +36,7 @@ export class FormSubmitDirective implements OnInit { @Input() markAsDirtyWhenSubmit = true; - @Output() readonly ngSubmit = new EventEmitter(); + readonly ngSubmit = output(); executedNgSubmit = false; diff --git a/npm/ng-packs/packages/core/src/lib/directives/init.directive.ts b/npm/ng-packs/packages/core/src/lib/directives/init.directive.ts index 1271f031ba..e4033f9f16 100644 --- a/npm/ng-packs/packages/core/src/lib/directives/init.directive.ts +++ b/npm/ng-packs/packages/core/src/lib/directives/init.directive.ts @@ -1,4 +1,4 @@ -import { Directive, Output, EventEmitter, ElementRef, AfterViewInit, inject } from '@angular/core'; +import { Directive, ElementRef, AfterViewInit, inject, output } from '@angular/core'; @Directive({ selector: '[abpInit]', @@ -6,7 +6,7 @@ import { Directive, Output, EventEmitter, ElementRef, AfterViewInit, inject } fr export class InitDirective implements AfterViewInit { private elRef = inject(ElementRef); - @Output('abpInit') readonly init = new EventEmitter>(); + readonly init = output>({ alias: 'abpInit' }); ngAfterViewInit() { this.init.emit(this.elRef); 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 index a1af9bf07e..2a3c8f0a80 100644 --- 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 @@ -1,4 +1,4 @@ -import { Directive, ElementRef, EventEmitter, OnInit, Output, inject } from '@angular/core'; +import { Directive, ElementRef, OnInit, inject, output } from '@angular/core'; import { fromEvent } from 'rxjs'; import { SubscriptionService } from '../services/subscription.service'; @@ -10,7 +10,7 @@ export class StopPropagationDirective implements OnInit { private el = inject(ElementRef); private subscription = inject(SubscriptionService); - @Output('click.stop') readonly stopPropEvent = new EventEmitter(); + readonly stopPropEvent = output({ alias: 'click.stop' }); ngOnInit(): void { this.subscription.addOne(fromEvent(this.el.nativeElement, 'click'), event => { diff --git a/npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.ts b/npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.ts index 5feac210e5..200e39736b 100644 --- a/npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.ts +++ b/npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, Output, inject, DOCUMENT } from '@angular/core'; +import { Component, Input, inject, DOCUMENT, output } from '@angular/core'; import { NgTemplateOutlet } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { ConfigStateService, LocalizationPipe, TrackByService } from '@abp/ng.core'; @@ -103,7 +103,7 @@ export class FeatureManagementComponent } } - @Output() readonly visibleChange = new EventEmitter(); + readonly visibleChange = output(); modalBusy = false; diff --git a/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts b/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts index b2612e9aaf..149b077b7a 100644 --- a/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts +++ b/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts @@ -19,14 +19,13 @@ import { computed, DOCUMENT, ElementRef, - EventEmitter, inject, Input, - Output, QueryList, signal, TrackByFunction, ViewChildren, + output } from '@angular/core'; import { concat, of } from 'rxjs'; import { finalize, switchMap, take, tap } from 'rxjs/operators'; @@ -160,7 +159,7 @@ export class PermissionManagementComponent } } - @Output() readonly visibleChange = new EventEmitter(); + readonly visibleChange = output(); @ViewChildren('selectAllInThisTabsRef') selectAllInThisTabsRef!: QueryList>; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/button/button.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/button/button.component.ts index 47272992fd..8ce05bd443 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/button/button.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/button/button.component.ts @@ -2,13 +2,12 @@ import { Component, ElementRef, - EventEmitter, Input, OnInit, - Output, Renderer2, ViewChild, inject, + output } from '@angular/core'; import { ABP, StopPropagationDirective } from '@abp/ng.core'; @@ -22,9 +21,9 @@ import { ABP, StopPropagationDirective } from '@abp/ng.core'; [attr.form]="formName" [class]="buttonClass" [disabled]="loading || disabled" - (click.stop)="click.next($event); abpClick.next($event)" - (focus)="focus.next($event); abpFocus.next($event)" - (blur)="blur.next($event); abpBlur.next($event)" + (click.stop)="click.emit($event); abpClick.emit($event)" + (focus)="focus.emit($event); abpFocus.emit($event)" + (blur)="blur.emit($event); abpBlur.emit($event)" > @@ -58,17 +57,17 @@ export class ButtonComponent implements OnInit { @Input() attributes?: ABP.Dictionary; - @Output() readonly click = new EventEmitter(); + readonly click = output(); - @Output() readonly focus = new EventEmitter(); + readonly focus = output(); - @Output() readonly blur = new EventEmitter(); + readonly blur = output(); - @Output() readonly abpClick = new EventEmitter(); + readonly abpClick = output(); - @Output() readonly abpFocus = new EventEmitter(); + readonly abpFocus = output(); - @Output() readonly abpBlur = new EventEmitter(); + readonly abpBlur = output(); @ViewChild('button', { static: true }) buttonRef!: ElementRef; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/checkbox/checkbox.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/checkbox/checkbox.component.ts index 8da578f9a7..be9c368704 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/checkbox/checkbox.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/checkbox/checkbox.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, forwardRef, Input, Output } from '@angular/core'; +import { Component, forwardRef, Input, output } from '@angular/core'; import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms'; import { AbstractNgModelComponent, LocalizationPipe } from '@abp/ng.core'; @@ -13,8 +13,8 @@ import { AbstractNgModelComponent, LocalizationPipe } from '@abp/ng.core'; [readonly]="checkboxReadonly" [class]="checkboxClass" [style]="checkboxStyle" - (blur)="checkboxBlur.next()" - (focus)="checkboxFocus.next()" + (blur)="checkboxBlur.emit()" + (focus)="checkboxFocus.emit()" /> @if (label) {