From d446a297fd4e0dc31b65aa49f5e5a5127d314b35 Mon Sep 17 00:00:00 2001 From: Fahri Gedik <53567152+fahrigedik@users.noreply.github.com> Date: Sat, 31 Jan 2026 12:37:57 +0300 Subject: [PATCH] Refactor EllipsisDirective to use signals and computed Replaces HostBinding and getter methods with Angular signals and computed properties for class, style, and title bindings. Improves reactivity and code clarity by leveraging Angular's new reactive primitives. --- .../src/lib/directives/ellipsis.directive.ts | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/ellipsis.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/ellipsis.directive.ts index 7ed5efe42b..f5ec50ec1f 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/directives/ellipsis.directive.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/ellipsis.directive.ts @@ -1,47 +1,48 @@ import { AfterViewInit, ChangeDetectorRef, + computed, Directive, ElementRef, - HostBinding, - Input, inject, - input + input, + signal } from '@angular/core'; @Directive({ selector: '[abpEllipsis]', + host: { + '[title]': 'effectiveTitle()', + '[class.abp-ellipsis-inline]': 'inlineClass()', + '[class.abp-ellipsis]': 'ellipsisClass()', + '[style.max-width]': 'maxWidth()' + } }) export class EllipsisDirective implements AfterViewInit { private cdRef = inject(ChangeDetectorRef); private elRef = inject(ElementRef); - readonly width = input(undefined, { alias: "abpEllipsis" }); + readonly width = input(undefined, { alias: 'abpEllipsis' }); + readonly title = input(undefined); + readonly enabled = input(true, { alias: 'abpEllipsisEnabled' }); - @HostBinding('title') - @Input() - title?: string; + private readonly autoTitle = signal(undefined); - readonly enabled = input(true, { alias: "abpEllipsisEnabled" }); + protected readonly effectiveTitle = computed(() => this.title() || this.autoTitle()); - @HostBinding('class.abp-ellipsis-inline') - get inlineClass() { - return this.enabled() && this.width(); - } + protected readonly inlineClass = computed(() => this.enabled() && !!this.width()); - @HostBinding('class.abp-ellipsis') - get class() { - return this.enabled() && !this.width(); - } + protected readonly ellipsisClass = computed(() => this.enabled() && !this.width()); - @HostBinding('style.max-width') - get maxWidth() { + protected readonly maxWidth = computed(() => { const width = this.width(); return this.enabled() && width ? width || '170px' : undefined; - } + }); ngAfterViewInit() { - this.title = this.title || (this.elRef.nativeElement as HTMLElement).innerText; - this.cdRef.detectChanges(); + if (!this.title()) { + this.autoTitle.set((this.elRef.nativeElement as HTMLElement).innerText); + this.cdRef.detectChanges(); + } } }