diff --git a/packages/abc/avatar-list/avatar-list.component.ts b/packages/abc/avatar-list/avatar-list.component.ts index d9d6b4a992..c176bb747d 100644 --- a/packages/abc/avatar-list/avatar-list.component.ts +++ b/packages/abc/avatar-list/avatar-list.component.ts @@ -7,12 +7,11 @@ import { ContentChildren, Input, OnChanges, - OnDestroy, Optional, QueryList, ViewEncapsulation } from '@angular/core'; -import { Subject, takeUntil } from 'rxjs'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { InputNumber, NumberInput } from '@delon/util/decorator'; import type { NgStyleInterface, NzSizeLDSType } from 'ng-zorro-antd/core/types'; @@ -31,13 +30,13 @@ import { AvatarListItemComponent } from './avatar-list-item.component'; changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None }) -export class AvatarListComponent implements AfterViewInit, OnChanges, OnDestroy { +export class AvatarListComponent implements AfterViewInit, OnChanges { static ngAcceptInputType_maxLength: NumberInput; private inited = false; @ContentChildren(AvatarListItemComponent, { descendants: false }) private _items!: QueryList; - private destroy$ = new Subject(); + private dir$ = this.directionality.change?.pipe(takeUntilDestroyed()); items: AvatarListItemComponent[] = []; exceedCount = 0; @@ -79,8 +78,9 @@ export class AvatarListComponent implements AfterViewInit, OnChanges, OnDestroy ngAfterViewInit(): void { this.dir = this.directionality.value; - this.directionality.change?.pipe(takeUntil(this.destroy$)).subscribe((direction: Direction) => { + this.dir$.subscribe((direction: Direction) => { this.dir = direction; + this.cdr.detectChanges(); }); this.gen(); this.inited = true; @@ -91,9 +91,4 @@ export class AvatarListComponent implements AfterViewInit, OnChanges, OnDestroy this.gen(); } } - - ngOnDestroy(): void { - this.destroy$.next(); - this.destroy$.complete(); - } } diff --git a/packages/abc/error-collect/error-collect.component.ts b/packages/abc/error-collect/error-collect.component.ts index 614b179e9a..4df8c0eb94 100644 --- a/packages/abc/error-collect/error-collect.component.ts +++ b/packages/abc/error-collect/error-collect.component.ts @@ -5,15 +5,17 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + DestroyRef, ElementRef, Inject, Input, - OnDestroy, OnInit, Optional, - ViewEncapsulation + ViewEncapsulation, + inject } from '@angular/core'; -import { interval, Subject, takeUntil } from 'rxjs'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { interval } from 'rxjs'; import { AlainConfigService } from '@delon/util/config'; import { InputNumber } from '@delon/util/decorator'; @@ -36,9 +38,9 @@ import type { NzSafeAny } from 'ng-zorro-antd/core/types'; changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None }) -export class ErrorCollectComponent implements OnInit, OnDestroy { +export class ErrorCollectComponent implements OnInit { private formEl: HTMLFormElement | null = null; - private destroy$ = new Subject(); + private destroy$ = inject(DestroyRef); _hiden = true; count = 0; @@ -83,11 +85,12 @@ export class ErrorCollectComponent implements OnInit, OnDestroy { private install(): void { this.dir = this.directionality.value; - this.directionality.change?.pipe(takeUntil(this.destroy$)).subscribe((direction: Direction) => { + this.directionality.change?.pipe(takeUntilDestroyed(this.destroy$)).subscribe((direction: Direction) => { this.dir = direction; + this.cdr.detectChanges(); }); interval(this.freq) - .pipe(takeUntil(this.destroy$)) + .pipe(takeUntilDestroyed(this.destroy$)) .subscribe(() => this.update()); this.update(); } @@ -111,9 +114,4 @@ export class ErrorCollectComponent implements OnInit, OnDestroy { if (this.formEl === null) throw new Error('No found form element'); this.install(); } - - ngOnDestroy(): void { - this.destroy$.next(); - this.destroy$.complete(); - } } diff --git a/packages/abc/exception/exception.component.ts b/packages/abc/exception/exception.component.ts index 2d02d306fe..0fabf60ffa 100644 --- a/packages/abc/exception/exception.component.ts +++ b/packages/abc/exception/exception.component.ts @@ -3,16 +3,17 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + DestroyRef, ElementRef, Input, - OnDestroy, OnInit, Optional, ViewChild, - ViewEncapsulation + ViewEncapsulation, + inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { DomSanitizer, SafeHtml, SafeUrl } from '@angular/platform-browser'; -import { Subject, takeUntil } from 'rxjs'; import { DelonLocaleService, LocaleData } from '@delon/theme'; import { isEmpty } from '@delon/util/browser'; @@ -33,10 +34,10 @@ export type ExceptionType = 403 | 404 | 500; changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None }) -export class ExceptionComponent implements OnInit, OnDestroy { +export class ExceptionComponent implements OnInit { static ngAcceptInputType_type: ExceptionType | string; - private destroy$ = new Subject(); + private destroy$ = inject(DestroyRef); @ViewChild('conTpl', { static: true }) private conTpl!: ElementRef; _type!: ExceptionType; @@ -113,15 +114,14 @@ export class ExceptionComponent implements OnInit, OnDestroy { ngOnInit(): void { this.dir = this.directionality.value; - this.directionality.change?.pipe(takeUntil(this.destroy$)).subscribe((direction: Direction) => { + this.directionality.change?.pipe(takeUntilDestroyed(this.destroy$)).subscribe((direction: Direction) => { this.dir = direction; + this.cdr.detectChanges(); + }); + this.i18n.change.pipe(takeUntilDestroyed(this.destroy$)).subscribe(() => { + this.locale = this.i18n.getData('exception'); + this.cdr.detectChanges(); }); - this.i18n.change.pipe(takeUntil(this.destroy$)).subscribe(() => (this.locale = this.i18n.getData('exception'))); this.checkContent(); } - - ngOnDestroy(): void { - this.destroy$.next(); - this.destroy$.complete(); - } } diff --git a/packages/abc/exception/exception.spec.ts b/packages/abc/exception/exception.spec.ts index 55a58e2a1a..f031766150 100644 --- a/packages/abc/exception/exception.spec.ts +++ b/packages/abc/exception/exception.spec.ts @@ -2,6 +2,7 @@ import { Directionality } from '@angular/cdk/bidi'; import { Component, DebugElement, ViewChild } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; +import { RouterTestingModule } from '@angular/router/testing'; import { createTestContext } from '@delon/testing'; import { DelonLocaleModule, DelonLocaleService, en_US } from '@delon/theme'; @@ -16,7 +17,7 @@ describe('abc: exception', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [ExceptionModule, DelonLocaleModule], + imports: [ExceptionModule, DelonLocaleModule, RouterTestingModule], declarations: [TestComponent] }); ({ fixture, dl, context } = createTestContext(TestComponent)); diff --git a/packages/abc/full-content/full-content.component.ts b/packages/abc/full-content/full-content.component.ts index 4a1508a9c6..e38215e25d 100644 --- a/packages/abc/full-content/full-content.component.ts +++ b/packages/abc/full-content/full-content.component.ts @@ -4,6 +4,7 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + DestroyRef, ElementRef, EventEmitter, Inject, @@ -12,10 +13,12 @@ import { OnDestroy, OnInit, Output, - ViewEncapsulation + ViewEncapsulation, + inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ActivationEnd, ActivationStart, Event, Router } from '@angular/router'; -import { fromEvent, Subject, debounceTime, filter, takeUntil } from 'rxjs'; +import { fromEvent, debounceTime, filter } from 'rxjs'; import { BooleanInput, InputBoolean, InputNumber, NumberInput } from '@delon/util/decorator'; import type { NzSafeAny } from 'ng-zorro-antd/core/types'; @@ -46,7 +49,7 @@ export class FullContentComponent implements AfterViewInit, OnInit, OnChanges, O private bodyEl!: HTMLElement; private inited = false; private id = `_full-content-${Math.random().toString(36).substring(2)}`; - private destroy$ = new Subject(); + private destroy$ = inject(DestroyRef); _height = 0; @@ -104,13 +107,13 @@ export class FullContentComponent implements AfterViewInit, OnInit, OnChanges, O // when window resize fromEvent(window, 'resize') - .pipe(takeUntil(this.destroy$), debounceTime(200)) + .pipe(takeUntilDestroyed(this.destroy$), debounceTime(200)) .subscribe(() => this.updateHeight()); // when servier changed this.srv.change .pipe( - takeUntil(this.destroy$), + takeUntilDestroyed(this.destroy$), filter(res => res !== null) ) .subscribe(() => this.toggle()); @@ -118,7 +121,7 @@ export class FullContentComponent implements AfterViewInit, OnInit, OnChanges, O // when router changed this.router.events .pipe( - takeUntil(this.destroy$), + takeUntilDestroyed(this.destroy$), filter((e: Event) => e instanceof ActivationStart || e instanceof ActivationEnd), debounceTime(200) ) @@ -148,8 +151,5 @@ export class FullContentComponent implements AfterViewInit, OnInit, OnChanges, O ngOnDestroy(): void { this.removeInBody(); - const { destroy$ } = this; - destroy$.next(); - destroy$.complete(); } } diff --git a/packages/abc/global-footer/global-footer.component.ts b/packages/abc/global-footer/global-footer.component.ts index e613b65e31..b837e3a215 100644 --- a/packages/abc/global-footer/global-footer.component.ts +++ b/packages/abc/global-footer/global-footer.component.ts @@ -1,19 +1,19 @@ import { Direction, Directionality } from '@angular/cdk/bidi'; import { ChangeDetectionStrategy, + ChangeDetectorRef, Component, ContentChildren, Inject, Input, - OnDestroy, OnInit, Optional, QueryList, ViewEncapsulation } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { DomSanitizer } from '@angular/platform-browser'; import { Router } from '@angular/router'; -import { takeUntil, Subject } from 'rxjs'; import { WINDOW } from '@delon/util/token'; import type { NzSafeAny } from 'ng-zorro-antd/core/types'; @@ -33,8 +33,8 @@ import { GlobalFooterLink } from './global-footer.types'; changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None }) -export class GlobalFooterComponent implements OnInit, OnDestroy { - private destroy$ = new Subject(); +export class GlobalFooterComponent implements OnInit { + private dir$ = this.directionality.change?.pipe(takeUntilDestroyed()); private _links: GlobalFooterLink[] = []; dir: Direction = 'ltr'; @@ -54,7 +54,8 @@ export class GlobalFooterComponent implements OnInit, OnDestroy { private router: Router, @Inject(WINDOW) private win: NzSafeAny, private dom: DomSanitizer, - @Optional() private directionality: Directionality + @Optional() private directionality: Directionality, + private cdr: ChangeDetectorRef ) {} to(item: GlobalFooterLink | GlobalFooterItemComponent): void { @@ -74,13 +75,9 @@ export class GlobalFooterComponent implements OnInit, OnDestroy { ngOnInit(): void { this.dir = this.directionality.value; - this.directionality.change?.pipe(takeUntil(this.destroy$)).subscribe((direction: Direction) => { + this.dir$.subscribe((direction: Direction) => { this.dir = direction; + this.cdr.detectChanges(); }); } - - ngOnDestroy(): void { - this.destroy$.next(); - this.destroy$.complete(); - } } diff --git a/packages/abc/media/media.component.ts b/packages/abc/media/media.component.ts index b7980c7fb5..715d787a0f 100644 --- a/packages/abc/media/media.component.ts +++ b/packages/abc/media/media.component.ts @@ -3,6 +3,7 @@ import { AfterViewInit, ChangeDetectionStrategy, Component, + DestroyRef, ElementRef, EventEmitter, Input, @@ -12,9 +13,11 @@ import { Output, Renderer2, SimpleChange, - ViewEncapsulation + ViewEncapsulation, + inject } from '@angular/core'; -import { Subject, timer, takeUntil, take } from 'rxjs'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { timer, take } from 'rxjs'; import type Plyr from 'plyr'; @@ -41,7 +44,7 @@ export class MediaComponent implements OnChanges, AfterViewInit, OnDestroy { private _p?: Plyr | null; private videoEl?: HTMLElement; - private destroy$ = new Subject(); + private destroy$ = inject(DestroyRef); @Input() type: MediaType = 'video'; @Input() source?: string | Plyr.SourceInfo; @@ -64,7 +67,7 @@ export class MediaComponent implements OnChanges, AfterViewInit, OnDestroy { @ZoneOutside() private initDelay(): void { timer(this.delay) - .pipe(takeUntil(this.destroy$)) + .pipe(takeUntilDestroyed(this.destroy$)) .subscribe(() => this.ngZone.runOutsideAngular(() => this.init())); } @@ -119,7 +122,7 @@ export class MediaComponent implements OnChanges, AfterViewInit, OnDestroy { } this.srv .notify() - .pipe(takeUntil(this.destroy$), take(1)) + .pipe(takeUntilDestroyed(this.destroy$), take(1)) .subscribe(() => this.initDelay()); this.srv.load(); @@ -135,9 +138,5 @@ export class MediaComponent implements OnChanges, AfterViewInit, OnDestroy { ngOnDestroy(): void { this.destroy(); this._p = null; - - const { destroy$ } = this; - destroy$.next(); - destroy$.complete(); } } diff --git a/packages/abc/page-header/page-header.component.ts b/packages/abc/page-header/page-header.component.ts index f58a962e27..44da4cd99f 100644 --- a/packages/abc/page-header/page-header.component.ts +++ b/packages/abc/page-header/page-header.component.ts @@ -9,7 +9,6 @@ import { Inject, Input, OnChanges, - OnDestroy, OnInit, Optional, Renderer2, @@ -17,8 +16,9 @@ import { ViewChild, ViewEncapsulation } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { NavigationEnd, Router } from '@angular/router'; -import { merge, Subject, filter, takeUntil } from 'rxjs'; +import { merge, filter } from 'rxjs'; import { ReuseTabService } from '@delon/abc/reuse-tab'; import { AlainI18NService, ALAIN_I18N_TOKEN, Menu, MenuService, SettingsService, TitleService } from '@delon/theme'; @@ -41,7 +41,7 @@ interface PageHeaderPath { changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None }) -export class PageHeaderComponent implements OnInit, OnChanges, AfterViewInit, OnDestroy { +export class PageHeaderComponent implements OnInit, OnChanges, AfterViewInit { static ngAcceptInputType_loading: BooleanInput; static ngAcceptInputType_wide: BooleanInput; static ngAcceptInputType_autoBreadcrumb: BooleanInput; @@ -51,7 +51,7 @@ export class PageHeaderComponent implements OnInit, OnChanges, AfterViewInit, On static ngAcceptInputType_fixedOffsetTop: NumberInput; static ngAcceptInputType_recursiveBreadcrumb: BooleanInput; - private destroy$ = new Subject(); + private dir$ = this.directionality.change?.pipe(takeUntilDestroyed()); @ViewChild('conTpl', { static: false }) private conTpl!: ElementRef; @ViewChild('affix', { static: false }) private affix!: NzAffixComponent; inited = false; @@ -127,15 +127,15 @@ export class PageHeaderComponent implements OnInit, OnChanges, AfterViewInit, On }); settings.notify .pipe( - takeUntil(this.destroy$), + takeUntilDestroyed(), filter(w => this.affix && w.type === 'layout' && w.name === 'collapsed') ) .subscribe(() => this.affix.updatePosition({} as NzSafeAny)); merge(menuSrv.change, router.events.pipe(filter(ev => ev instanceof NavigationEnd)), i18nSrv.change) .pipe( - filter(() => this.inited), - takeUntil(this.destroy$) + takeUntilDestroyed(), + filter(() => this.inited) ) .subscribe(() => this.refresh()); } @@ -199,7 +199,7 @@ export class PageHeaderComponent implements OnInit, OnChanges, AfterViewInit, On ngOnInit(): void { this.dir = this.directionality.value; - this.directionality.change?.pipe(takeUntil(this.destroy$)).subscribe((direction: Direction) => { + this.dir$.subscribe((direction: Direction) => { this.dir = direction; this.cdr.detectChanges(); }); @@ -216,9 +216,4 @@ export class PageHeaderComponent implements OnInit, OnChanges, AfterViewInit, On this.refresh(); } } - - ngOnDestroy(): void { - this.destroy$.next(); - this.destroy$.complete(); - } } diff --git a/packages/abc/pdf/pdf.component.ts b/packages/abc/pdf/pdf.component.ts index 49d2b1952c..6a7ea91ba5 100644 --- a/packages/abc/pdf/pdf.component.ts +++ b/packages/abc/pdf/pdf.component.ts @@ -5,6 +5,7 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + DestroyRef, ElementRef, EventEmitter, Inject, @@ -15,9 +16,11 @@ import { Optional, Output, SimpleChange, - ViewEncapsulation + ViewEncapsulation, + inject } from '@angular/core'; -import { fromEvent, Subject, timer, debounceTime, filter, takeUntil } from 'rxjs'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { fromEvent, timer, debounceTime, filter } from 'rxjs'; import type { PDFDocumentLoadingTask, PDFDocumentProxy } from 'pdfjs-dist'; import type { EventBus } from 'pdfjs-dist/types/web/event_utils'; @@ -63,7 +66,7 @@ export class PdfComponent implements OnChanges, AfterViewInit, OnDestroy { static ngAcceptInputType_removePageBorders: BooleanInput; inited = false; - private destroy$ = new Subject(); + private destroy$ = inject(DestroyRef); private lib: string = ''; private _pdf?: PDFDocumentProxy | null; private loadingTask?: PDFDocumentLoadingTask; @@ -212,7 +215,7 @@ export class PdfComponent implements OnChanges, AfterViewInit, OnDestroy { this.win.pdfjsLib.GlobalWorkerOptions.workerSrc = `${this.lib}build/pdf.worker.min.js`; timer(this.delay ?? 0) - .pipe(takeUntil(this.destroy$)) + .pipe(takeUntilDestroyed(this.destroy$)) .subscribe(() => this.load()); } @@ -312,7 +315,7 @@ export class PdfComponent implements OnChanges, AfterViewInit, OnDestroy { private timeExec(fn: () => void): void { this.ngZone.runOutsideAngular(() => { timer(0) - .pipe(takeUntil(this.destroy$)) + .pipe(takeUntilDestroyed(this.destroy$)) .subscribe(() => this.ngZone.runOutsideAngular(() => fn())); }); } @@ -480,7 +483,7 @@ export class PdfComponent implements OnChanges, AfterViewInit, OnDestroy { .pipe( debounceTime(100), filter(() => this.autoReSize && this._pdf != null), - takeUntil(this.destroy$) + takeUntilDestroyed(this.destroy$) ) .subscribe(() => this.updateSize()); } @@ -492,10 +495,6 @@ export class PdfComponent implements OnChanges, AfterViewInit, OnDestroy { } ngOnDestroy(): void { - const { destroy$ } = this; - destroy$.next(); - destroy$.complete(); - this.destroy(); } } diff --git a/packages/abc/result/result.component.ts b/packages/abc/result/result.component.ts index 919f70a126..34fbb49543 100644 --- a/packages/abc/result/result.component.ts +++ b/packages/abc/result/result.component.ts @@ -1,15 +1,15 @@ import { Direction, Directionality } from '@angular/cdk/bidi'; import { ChangeDetectionStrategy, + ChangeDetectorRef, Component, Input, - OnDestroy, OnInit, Optional, TemplateRef, ViewEncapsulation } from '@angular/core'; -import { Subject, takeUntil } from 'rxjs'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ selector: 'result', @@ -23,8 +23,8 @@ import { Subject, takeUntil } from 'rxjs'; changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None }) -export class ResultComponent implements OnInit, OnDestroy { - private destroy$ = new Subject(); +export class ResultComponent implements OnInit { + private dir$ = this.directionality.change?.pipe(takeUntilDestroyed()); _type = ''; _icon = ''; @Input() @@ -48,17 +48,16 @@ export class ResultComponent implements OnInit, OnDestroy { @Input() extra?: string | TemplateRef; dir: Direction = 'ltr'; - constructor(@Optional() private directionality: Directionality) {} + constructor( + @Optional() private directionality: Directionality, + private cdr: ChangeDetectorRef + ) {} ngOnInit(): void { this.dir = this.directionality.value; - this.directionality.change?.pipe(takeUntil(this.destroy$)).subscribe((direction: Direction) => { + this.dir$.subscribe((direction: Direction) => { this.dir = direction; + this.cdr.detectChanges(); }); } - - ngOnDestroy(): void { - this.destroy$.next(); - this.destroy$.complete(); - } } diff --git a/packages/abc/reuse-tab/reuse-tab.component.ts b/packages/abc/reuse-tab/reuse-tab.component.ts index c33cfaaefe..99cc0bce6f 100644 --- a/packages/abc/reuse-tab/reuse-tab.component.ts +++ b/packages/abc/reuse-tab/reuse-tab.component.ts @@ -5,11 +5,11 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + DestroyRef, EventEmitter, Inject, Input, OnChanges, - OnDestroy, OnInit, Optional, Output, @@ -17,10 +17,12 @@ import { SimpleChanges, TemplateRef, ViewChild, - ViewEncapsulation + ViewEncapsulation, + inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ActivatedRoute, Router } from '@angular/router'; -import { Subject, debounceTime, filter, takeUntil, of } from 'rxjs'; +import { debounceTime, filter, of } from 'rxjs'; import { AlainI18NService, ALAIN_I18N_TOKEN } from '@delon/theme'; import { BooleanInput, InputBoolean, InputNumber, NumberInput } from '@delon/util/decorator'; @@ -59,7 +61,7 @@ import { ReuseTabStorageState, REUSE_TAB_STORAGE_KEY, REUSE_TAB_STORAGE_STATE } changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None }) -export class ReuseTabComponent implements OnInit, OnChanges, OnDestroy { +export class ReuseTabComponent implements OnInit, OnChanges { static ngAcceptInputType_debug: BooleanInput; static ngAcceptInputType_max: NumberInput; static ngAcceptInputType_tabMaxWidth: NumberInput; @@ -69,7 +71,7 @@ export class ReuseTabComponent implements OnInit, OnChanges, OnDestroy { static ngAcceptInputType_storageState: BooleanInput; @ViewChild('tabset') private tabset!: NzTabSetComponent; - private destroy$ = new Subject(); + private destroy$ = inject(DestroyRef); private _keepingScrollContainer?: Element; list: ReuseItem[] = []; item?: ReuseItem; @@ -297,7 +299,7 @@ export class ReuseTabComponent implements OnInit, OnChanges, OnDestroy { ngOnInit(): void { this.dir = this.directionality.value; - this.directionality.change?.pipe(takeUntil(this.destroy$)).subscribe((direction: Direction) => { + this.directionality.change?.pipe(takeUntilDestroyed(this.destroy$)).subscribe((direction: Direction) => { this.dir = direction; this.cdr.detectChanges(); }); @@ -306,7 +308,7 @@ export class ReuseTabComponent implements OnInit, OnChanges, OnDestroy { return; } - this.srv.change.pipe(takeUntil(this.destroy$)).subscribe(res => { + this.srv.change.pipe(takeUntilDestroyed(this.destroy$)).subscribe(res => { switch (res?.active) { case 'title': this.updateTitle(res); @@ -324,7 +326,7 @@ export class ReuseTabComponent implements OnInit, OnChanges, OnDestroy { this.i18nSrv.change .pipe( filter(() => this.srv.inited), - takeUntil(this.destroy$), + takeUntilDestroyed(this.destroy$), debounceTime(100) ) .subscribe(() => this.genList({ active: 'title' })); @@ -351,10 +353,4 @@ export class ReuseTabComponent implements OnInit, OnChanges, OnDestroy { this.cdr.detectChanges(); } - - ngOnDestroy(): void { - const { destroy$ } = this; - destroy$.next(); - destroy$.complete(); - } } diff --git a/packages/abc/se/se.component.ts b/packages/abc/se/se.component.ts index 97e941e0af..50ba4a19d6 100644 --- a/packages/abc/se/se.component.ts +++ b/packages/abc/se/se.component.ts @@ -5,19 +5,21 @@ import { ChangeDetectorRef, Component, ContentChild, + DestroyRef, ElementRef, Host, Input, OnChanges, - OnDestroy, Optional, Renderer2, TemplateRef, ViewChild, - ViewEncapsulation + ViewEncapsulation, + inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { FormControlName, NgModel, RequiredValidator, Validator } from '@angular/forms'; -import { Subject, filter, takeUntil } from 'rxjs'; +import { filter } from 'rxjs'; import { ResponsiveService } from '@delon/theme'; import { isEmpty } from '@delon/util/browser'; @@ -49,7 +51,7 @@ let nextUniqueId = 0; changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None }) -export class SEComponent implements OnChanges, AfterContentInit, AfterViewInit, OnDestroy { +export class SEComponent implements OnChanges, AfterContentInit, AfterViewInit { static ngAcceptInputType_col: NumberInput; static ngAcceptInputType_required: BooleanInput; static ngAcceptInputType_line: BooleanInput; @@ -58,7 +60,7 @@ export class SEComponent implements OnChanges, AfterContentInit, AfterViewInit, static ngAcceptInputType_hideLabel: BooleanInput; private el: HTMLElement; - private destroy$ = new Subject(); + private destroy$ = inject(DestroyRef); @ContentChild(NgModel, { static: true }) private readonly ngModel?: NgModel; @ContentChild(FormControlName, { static: true }) private readonly formControlName?: FormControlName; @@ -133,7 +135,7 @@ export class SEComponent implements OnChanges, AfterContentInit, AfterViewInit, this.el = el.nativeElement; parent.errorNotify .pipe( - takeUntil(this.destroy$), + takeUntilDestroyed(this.destroy$), filter(w => this.inited && this.ngControl != null && this.ngControl.name === w.name) ) .subscribe(item => { @@ -163,7 +165,9 @@ export class SEComponent implements OnChanges, AfterContentInit, AfterViewInit, if (!this.ngControl || this.isBindModel) return; this.isBindModel = true; - this.ngControl.statusChanges!.pipe(takeUntil(this.destroy$)).subscribe(res => this.updateStatus(res === 'INVALID')); + this.ngControl + .statusChanges!.pipe(takeUntilDestroyed(this.destroy$)) + .subscribe(res => this.updateStatus(res === 'INVALID')); if (this._autoId) { const controlAccessor = this.ngControl.valueAccessor as NzSafeAny; const control = (controlAccessor?.elementRef || controlAccessor?._elementRef)?.nativeElement as HTMLElement; @@ -232,10 +236,4 @@ export class SEComponent implements OnChanges, AfterContentInit, AfterViewInit, }); } } - - ngOnDestroy(): void { - const { destroy$ } = this; - destroy$.next(); - destroy$.complete(); - } } diff --git a/packages/abc/st/demo/virtual.md b/packages/abc/st/demo/virtual.md index 3d12d5751b..b1b9dceda3 100644 --- a/packages/abc/st/demo/virtual.md +++ b/packages/abc/st/demo/virtual.md @@ -14,30 +14,31 @@ title: Virtual scrolling combine with [cdk scrolling](https://material.angular.io/cdk/scrolling/overview) used to display large data, you can get `cdkVirtualScrollViewport` in `STComponent` and find more API [here](https://material.angular.io/cdk/scrolling/api#CdkVirtualScrollViewport). ```ts -import { AfterViewInit, Component, OnDestroy, ViewChild } from '@angular/core'; +import { AfterViewInit, Component, DestroyRef, ViewChild, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; + import { STColumn, STComponent, STPage } from '@delon/abc/st'; -import { Subject, takeUntil } from 'rxjs'; @Component({ selector: 'app-demo', template: ` - `, + ` }) -export class DemoComponent implements AfterViewInit, OnDestroy { - private destroy$ = new Subject(); +export class DemoComponent implements AfterViewInit { + private destroy$ = inject(DestroyRef); @ViewChild('st', { static: false }) st!: STComponent; page: STPage = { front: false, - show: false, + show: false }; data: Array<{ id: number; price: number }> = Array(2000) .fill({}) .map((_, idx) => ({ id: idx + 1, - price: ~~(Math.random() * 100), + price: ~~(Math.random() * 100) })); columns: STColumn[] = [ { title: '编号', index: 'id', width: 100 }, @@ -50,7 +51,7 @@ export class DemoComponent implements AfterViewInit, OnDestroy { { title: '价格7', index: 'price', width: 100 }, { title: '价格8', index: 'price', width: 100 }, { title: '价格9', index: 'price', width: 100 }, - { title: '价格10', index: 'price', width: 100 }, + { title: '价格10', index: 'price', width: 100 } ]; scrollToIndex(index: number): void { @@ -58,14 +59,9 @@ export class DemoComponent implements AfterViewInit, OnDestroy { } ngAfterViewInit(): void { - this.st.cdkVirtualScrollViewport.scrolledIndexChange.pipe(takeUntil(this.destroy$)).subscribe(data => { + this.st.cdkVirtualScrollViewport.scrolledIndexChange.pipe(takeUntilDestroyed(this.destroy$)).subscribe(data => { console.log('scroll index to', data); }); } - - ngOnDestroy(): void { - this.destroy$.next(); - this.destroy$.complete(); - } } ``` diff --git a/packages/abc/st/st.component.ts b/packages/abc/st/st.component.ts index 24b66318af..9d770054d0 100644 --- a/packages/abc/st/st.component.ts +++ b/packages/abc/st/st.component.ts @@ -5,9 +5,11 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + DestroyRef, ElementRef, EventEmitter, Host, + inject, Inject, Input, OnChanges, @@ -21,8 +23,9 @@ import { ViewChild, ViewEncapsulation } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { Router } from '@angular/router'; -import { from, isObservable, Observable, of, Subject, Subscription, filter, takeUntil } from 'rxjs'; +import { from, isObservable, Observable, of, Subscription, filter } from 'rxjs'; import { AlainI18NService, @@ -109,7 +112,8 @@ export class STComponent implements AfterViewInit, OnChanges, OnDestroy { static ngAcceptInputType_virtualMaxBufferPx: NumberInput; static ngAcceptInputType_virtualMinBufferPx: NumberInput; - private destroy$ = new Subject(); + private destroy$ = inject(DestroyRef); + private isDestroy = false; private data$?: Subscription; private totalTpl = ``; cog!: AlainSTConfig; @@ -261,7 +265,7 @@ export class STComponent implements AfterViewInit, OnChanges, OnDestroy { configSrv: AlainConfigService, private cms: NzContextMenuService ) { - this.delonI18n.change.pipe(takeUntil(this.destroy$)).subscribe(() => { + this.delonI18n.change.pipe(takeUntilDestroyed()).subscribe(() => { this.locale = this.delonI18n.getData('st'); if (this._columns.length > 0) { this.updateTotalTpl(); @@ -271,7 +275,7 @@ export class STComponent implements AfterViewInit, OnChanges, OnDestroy { i18nSrv.change .pipe( - takeUntil(this.destroy$), + takeUntilDestroyed(), filter(() => this._columns.length > 0) ) .subscribe(() => this.refreshColumns()); @@ -375,7 +379,7 @@ export class STComponent implements AfterViewInit, OnChanges, OnDestroy { customRequest: this.customRequest || this.cog.customRequest, ...options }) - .pipe(takeUntil(this.destroy$)) + .pipe(takeUntilDestroyed(this.destroy$)) .subscribe({ next: result => resolvePromise(result), error: error => { @@ -417,7 +421,7 @@ export class STComponent implements AfterViewInit, OnChanges, OnDestroy { return this._refCheck(); } catch (error) { this.setLoading(false); - if (!this.destroy$.closed) { + if (!this.isDestroy) { this.cdr.detectChanges(); this.error.emit({ type: 'req', error }); } @@ -813,7 +817,7 @@ export class STComponent implements AfterViewInit, OnChanges, OnDestroy { }); (isObservable(obs$) ? obs$ : of(obs$)) .pipe( - takeUntil(this.destroy$), + takeUntilDestroyed(this.destroy$), filter(res => res.length > 0) ) .subscribe(res => { @@ -918,8 +922,7 @@ export class STComponent implements AfterViewInit, OnChanges, OnDestroy { } ngOnDestroy(): void { - this.destroy$.next(); - this.destroy$.complete(); + this.isDestroy = true; } } diff --git a/packages/abc/tag-select/tag-select.component.ts b/packages/abc/tag-select/tag-select.component.ts index 2bafaadd33..c2dc3a06f7 100644 --- a/packages/abc/tag-select/tag-select.component.ts +++ b/packages/abc/tag-select/tag-select.component.ts @@ -3,15 +3,16 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + DestroyRef, EventEmitter, Input, - OnDestroy, OnInit, Optional, Output, - ViewEncapsulation + ViewEncapsulation, + inject } from '@angular/core'; -import { Subject, takeUntil } from 'rxjs'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { DelonLocaleService, LocaleData } from '@delon/theme'; import { BooleanInput, InputBoolean } from '@delon/util/decorator'; @@ -31,10 +32,10 @@ import { BooleanInput, InputBoolean } from '@delon/util/decorator'; changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None }) -export class TagSelectComponent implements OnInit, OnDestroy { +export class TagSelectComponent implements OnInit { static ngAcceptInputType_expandable: BooleanInput; - private destroy$ = new Subject(); + private destroy$ = inject(DestroyRef); locale: LocaleData = {}; expand = false; dir: Direction = 'ltr'; @@ -51,10 +52,10 @@ export class TagSelectComponent implements OnInit, OnDestroy { ngOnInit(): void { this.dir = this.directionality.value; - this.directionality.change?.pipe(takeUntil(this.destroy$)).subscribe((direction: Direction) => { + this.directionality.change?.pipe(takeUntilDestroyed(this.destroy$)).subscribe((direction: Direction) => { this.dir = direction; }); - this.i18n.change.pipe(takeUntil(this.destroy$)).subscribe(() => { + this.i18n.change.pipe(takeUntilDestroyed(this.destroy$)).subscribe(() => { this.locale = this.i18n.getData('tagSelect'); this.cdr.detectChanges(); }); @@ -64,9 +65,4 @@ export class TagSelectComponent implements OnInit, OnDestroy { this.expand = !this.expand; this.change.emit(this.expand); } - - ngOnDestroy(): void { - this.destroy$.next(); - this.destroy$.complete(); - } } diff --git a/packages/chart/chart-echarts/echarts.component.ts b/packages/chart/chart-echarts/echarts.component.ts index e44c81ee43..ad3de62040 100644 --- a/packages/chart/chart-echarts/echarts.component.ts +++ b/packages/chart/chart-echarts/echarts.component.ts @@ -3,6 +3,7 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + DestroyRef, ElementRef, EventEmitter, Input, @@ -11,9 +12,11 @@ import { OnInit, Output, ViewChild, - ViewEncapsulation + ViewEncapsulation, + inject } from '@angular/core'; -import { fromEvent, Subject, debounceTime, filter, takeUntil } from 'rxjs'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { fromEvent, debounceTime, filter } from 'rxjs'; import { NumberInput, ZoneOutside } from '@delon/util/decorator'; import type { NzSafeAny } from 'ng-zorro-antd/core/types'; @@ -48,7 +51,7 @@ export class ChartEChartsComponent implements OnInit, OnDestroy { static ngAcceptInputType_height: NumberInput; @ViewChild('container', { static: true }) private node!: ElementRef; - private destroy$ = new Subject(); + private destroy$ = inject(DestroyRef); private _chart: ChartECharts | null = null; private _theme?: string | Record | null; private _initOpt?: { @@ -106,7 +109,7 @@ export class ChartEChartsComponent implements OnInit, OnDestroy { ) { this.srv.notify .pipe( - takeUntil(this.destroy$), + takeUntilDestroyed(), filter(() => !this.loaded) ) .subscribe(() => this.load()); @@ -176,7 +179,7 @@ export class ChartEChartsComponent implements OnInit, OnDestroy { fromEvent(window, 'resize') .pipe( - takeUntil(this.destroy$), + takeUntilDestroyed(this.destroy$), filter(() => !!this._chart), debounceTime(200) ) @@ -185,8 +188,6 @@ export class ChartEChartsComponent implements OnInit, OnDestroy { ngOnDestroy(): void { this.on.forEach(item => this._chart?.off(item.eventName)); - this.destroy$.next(); - this.destroy$.complete(); this.destroy(); } } diff --git a/packages/form/src/sf.component.ts b/packages/form/src/sf.component.ts index 002fda9677..d26e160a17 100644 --- a/packages/form/src/sf.component.ts +++ b/packages/form/src/sf.component.ts @@ -16,8 +16,9 @@ import { TemplateRef, ViewEncapsulation } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { DomSanitizer } from '@angular/platform-browser'; -import { merge, Observable, Subject, filter, takeUntil } from 'rxjs'; +import { merge, Observable, filter } from 'rxjs'; import { ACLService } from '@delon/acl'; import { AlainI18NService, ALAIN_I18N_TOKEN, DelonLocaleService, LocaleData } from '@delon/theme'; @@ -84,7 +85,6 @@ export class SFComponent implements OnInit, OnChanges, OnDestroy { static ngAcceptInputType_cleanValue: BooleanInput; static ngAcceptInputType_delay: BooleanInput; - private destroy$ = new Subject(); private _renders = new Map>(); private _item!: Record; private _valid = true; @@ -277,7 +277,7 @@ export class SFComponent implements OnInit, OnChanges, OnDestroy { this.firstVisual = this.options.firstVisual as boolean; this.autocomplete = this.options.autocomplete as 'on' | 'off'; this.delay = this.options.delay as boolean; - this.localeSrv.change.pipe(takeUntil(this.destroy$)).subscribe(() => { + this.localeSrv.change.pipe(takeUntilDestroyed()).subscribe(() => { this.locale = this.localeSrv.getData('sf'); if (this._inited) { this.validator({ emitError: false, onlyRoot: false }); @@ -293,7 +293,7 @@ export class SFComponent implements OnInit, OnChanges, OnDestroy { merge(...(refSchemas as Array>)) .pipe( filter(() => this._inited), - takeUntil(this.destroy$) + takeUntilDestroyed() ) .subscribe(() => this.refreshSchema()); } @@ -691,8 +691,5 @@ export class SFComponent implements OnInit, OnChanges, OnDestroy { ngOnDestroy(): void { this.cleanRootSub(); this.terminator.destroy(); - const { destroy$ } = this; - destroy$.next(); - destroy$.complete(); } } diff --git a/packages/theme/layout-default/layout-header.component.ts b/packages/theme/layout-default/layout-header.component.ts index a25cfa3c87..e7228fd31a 100644 --- a/packages/theme/layout-default/layout-header.component.ts +++ b/packages/theme/layout-default/layout-header.component.ts @@ -3,12 +3,13 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + DestroyRef, Input, - OnDestroy, QueryList, - TemplateRef + TemplateRef, + inject } from '@angular/core'; -import { Subject, takeUntil } from 'rxjs'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { App, SettingsService } from '@delon/theme'; import type { NzSafeAny } from 'ng-zorro-antd/core/types'; @@ -61,8 +62,8 @@ interface LayoutDefaultHeaderItem { }, changeDetection: ChangeDetectionStrategy.OnPush }) -export class LayoutDefaultHeaderComponent implements AfterViewInit, OnDestroy { - private destroy$ = new Subject(); +export class LayoutDefaultHeaderComponent implements AfterViewInit { + private destroy$ = inject(DestroyRef); @Input() items!: QueryList; @@ -101,17 +102,12 @@ export class LayoutDefaultHeaderComponent implements AfterViewInit, OnDestroy { } ngAfterViewInit(): void { - this.items.changes.pipe(takeUntil(this.destroy$)).subscribe(() => this.refresh()); - this.srv.options$.pipe(takeUntil(this.destroy$)).subscribe(() => this.cdr.detectChanges()); + this.items.changes.pipe(takeUntilDestroyed(this.destroy$)).subscribe(() => this.refresh()); + this.srv.options$.pipe(takeUntilDestroyed(this.destroy$)).subscribe(() => this.cdr.detectChanges()); this.refresh(); } toggleCollapsed(): void { this.srv.toggleCollapsed(); } - - ngOnDestroy(): void { - this.destroy$.next(); - this.destroy$.complete(); - } } diff --git a/packages/theme/layout-default/layout-nav.component.ts b/packages/theme/layout-default/layout-nav.component.ts index 971409f120..7d0836b819 100644 --- a/packages/theme/layout-default/layout-nav.component.ts +++ b/packages/theme/layout-default/layout-nav.component.ts @@ -4,6 +4,7 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + DestroyRef, EventEmitter, Inject, Input, @@ -13,11 +14,13 @@ import { Optional, Output, Renderer2, - ViewEncapsulation + ViewEncapsulation, + inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; import { NavigationEnd, Router } from '@angular/router'; -import { Subject, filter, takeUntil } from 'rxjs'; +import { filter } from 'rxjs'; import { Menu, MenuIcon, MenuInner, MenuService, SettingsService } from '@delon/theme'; import { BooleanInput, InputBoolean, InputNumber, NumberInput, ZoneOutside } from '@delon/util/decorator'; @@ -52,7 +55,7 @@ export class LayoutDefaultNavComponent implements OnInit, OnDestroy { static ngAcceptInputType_maxLevelIcon: NumberInput; private bodyEl!: HTMLBodyElement; - private destroy$ = new Subject(); + private destroy$ = inject(DestroyRef); private floatingEl!: HTMLDivElement; dir: Direction = 'ltr'; list: Nav[] = []; @@ -228,9 +231,9 @@ export class LayoutDefaultNavComponent implements OnInit, OnDestroy { } ngOnInit(): void { - const { doc, router, destroy$, menuSrv, settings, cdr } = this; + const { doc, router, menuSrv, settings, cdr } = this; this.bodyEl = doc.querySelector('body'); - menuSrv.change.pipe(takeUntil(destroy$)).subscribe(data => { + menuSrv.change.pipe(takeUntilDestroyed(this.destroy$)).subscribe(data => { menuSrv.visit(data, (i: Nav, _p, depth) => { i._text = this.sanitizer.bypassSecurityTrustHtml(i.text!); i._needIcon = depth! <= this.maxLevelIcon && !!i.icon; @@ -250,7 +253,7 @@ export class LayoutDefaultNavComponent implements OnInit, OnDestroy { this.list = data.filter((w: Nav) => w._hidden !== true); cdr.detectChanges(); }); - router.events.pipe(takeUntil(destroy$)).subscribe(e => { + router.events.pipe(takeUntilDestroyed(this.destroy$)).subscribe(e => { if (e instanceof NavigationEnd) { this.openByUrl(e.urlAfterRedirects); this.underPad(); @@ -259,15 +262,16 @@ export class LayoutDefaultNavComponent implements OnInit, OnDestroy { }); settings.notify .pipe( - takeUntil(destroy$), + takeUntilDestroyed(this.destroy$), filter(t => t.type === 'layout' && t.name === 'collapsed') ) .subscribe(() => this.clearFloating()); this.underPad(); this.dir = this.directionality.value; - this.directionality.change?.pipe(takeUntil(destroy$)).subscribe((direction: Direction) => { + this.directionality.change?.pipe(takeUntilDestroyed(this.destroy$)).subscribe((direction: Direction) => { this.dir = direction; + this.cdr.detectChanges(); }); this.openByUrl(router.url); this.ngZone.runOutsideAngular(() => this.genFloating()); @@ -289,8 +293,6 @@ export class LayoutDefaultNavComponent implements OnInit, OnDestroy { } ngOnDestroy(): void { - this.destroy$.next(); - this.destroy$.complete(); this.clearFloating(); } diff --git a/packages/theme/layout-default/layout.component.ts b/packages/theme/layout-default/layout.component.ts index a2de5aab62..0fbfdab629 100644 --- a/packages/theme/layout-default/layout.component.ts +++ b/packages/theme/layout-default/layout.component.ts @@ -5,11 +5,11 @@ import { ElementRef, Inject, Input, - OnDestroy, QueryList, Renderer2, TemplateRef } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { NavigationCancel, NavigationEnd, @@ -19,7 +19,7 @@ import { Router, Event } from '@angular/router'; -import { Subject, filter, takeUntil } from 'rxjs'; +import { filter } from 'rxjs'; import { SettingsService } from '@delon/theme'; import { updateHostClass } from '@delon/util/browser'; @@ -59,7 +59,7 @@ import { LayoutDefaultOptions } from './types'; ` }) -export class LayoutDefaultComponent implements OnDestroy { +export class LayoutDefaultComponent { static ngAcceptInputType_fetchingStrictly: BooleanInput; static ngAcceptInputType_fetching: BooleanInput; @@ -82,7 +82,6 @@ export class LayoutDefaultComponent implements OnDestroy { @Input() @InputBoolean() fetchingStrictly = false; @Input() @InputBoolean() fetching = false; - private destroy$ = new Subject(); private isFetching = false; get showFetching(): boolean { @@ -111,15 +110,14 @@ export class LayoutDefaultComponent implements OnDestroy { @Inject(DOCUMENT) private doc: NzSafeAny, private srv: LayoutDefaultService ) { - const { destroy$ } = this; router.events .pipe( - takeUntil(destroy$), + takeUntilDestroyed(), filter(() => !this.fetchingStrictly) ) .subscribe(ev => this.processEv(ev)); - this.srv.options$.pipe(takeUntil(destroy$)).subscribe(() => this.setClass()); - this.settings.notify.pipe(takeUntil(destroy$)).subscribe(() => this.setClass()); + this.srv.options$.pipe(takeUntilDestroyed()).subscribe(() => this.setClass()); + this.settings.notify.pipe(takeUntilDestroyed()).subscribe(() => this.setClass()); } processEv(ev: Event): void { @@ -157,9 +155,4 @@ export class LayoutDefaultComponent implements OnDestroy { doc.body.classList[layout.colorWeak ? 'add' : 'remove']('color-weak'); } - - ngOnDestroy(): void { - this.destroy$.next(); - this.destroy$.complete(); - } } diff --git a/packages/theme/setting-drawer/setting-drawer.component.ts b/packages/theme/setting-drawer/setting-drawer.component.ts index 31f9c7a87f..766d2fdbbf 100644 --- a/packages/theme/setting-drawer/setting-drawer.component.ts +++ b/packages/theme/setting-drawer/setting-drawer.component.ts @@ -8,11 +8,10 @@ import { Input, isDevMode, NgZone, - OnDestroy, OnInit, Optional } from '@angular/core'; -import { Subject, takeUntil } from 'rxjs'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { Layout, SettingsService } from '@delon/theme'; import { copy } from '@delon/util/browser'; @@ -32,14 +31,14 @@ import { ALAINDEFAULTVAR, DEFAULT_COLORS, DEFAULT_VARS } from './setting-drawer. }, changeDetection: ChangeDetectionStrategy.OnPush }) -export class SettingDrawerComponent implements OnInit, OnDestroy { +export class SettingDrawerComponent implements OnInit { @Input() @InputBoolean() autoApplyColor = true; @Input() compilingText = 'Compiling...'; @Input() devTips = `When the color can't be switched, you need to run it once: npm run color-less`; @Input() lessJs = 'https://cdn.jsdelivr.net/npm/less'; private loadedLess = false; - private destroy$ = new Subject(); + private dir$ = this.directionality.change?.pipe(takeUntilDestroyed()); dir: Direction = 'ltr'; isDev = isDevMode(); collapse = false; @@ -73,8 +72,9 @@ export class SettingDrawerComponent implements OnInit, OnDestroy { ngOnInit(): void { this.dir = this.directionality.value; - this.directionality.change?.pipe(takeUntil(this.destroy$)).subscribe((direction: Direction) => { + this.dir$.subscribe((direction: Direction) => { this.dir = direction; + this.cdr.detectChanges(); }); if (this.autoApplyColor && this.color !== this.DEFAULT_PRIMARY) { this.changeColor(this.color); @@ -183,9 +183,4 @@ export class SettingDrawerComponent implements OnInit, OnDestroy { copy(copyContent); this.msg.success('Copy success'); } - - ngOnDestroy(): void { - this.destroy$.next(); - this.destroy$.complete(); - } } diff --git a/packages/theme/src/services/title/title.service.ts b/packages/theme/src/services/title/title.service.ts index 2f706272ae..3e81d84ce6 100644 --- a/packages/theme/src/services/title/title.service.ts +++ b/packages/theme/src/services/title/title.service.ts @@ -1,8 +1,9 @@ import { DOCUMENT } from '@angular/common'; -import { Inject, Injectable, Injector, OnDestroy, Optional } from '@angular/core'; +import { DestroyRef, Inject, Injectable, Injector, OnDestroy, Optional, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { Title } from '@angular/platform-browser'; import { ActivatedRoute, Router } from '@angular/router'; -import { Observable, of, map, delay, isObservable, switchMap, Subject, takeUntil, Subscription } from 'rxjs'; +import { Observable, of, map, delay, isObservable, switchMap, Subscription } from 'rxjs'; import type { NzSafeAny } from 'ng-zorro-antd/core/types'; @@ -16,11 +17,11 @@ export interface RouteTitle { @Injectable({ providedIn: 'root' }) export class TitleService implements OnDestroy { + private destroy$ = inject(DestroyRef); private _prefix: string = ''; private _suffix: string = ''; private _separator: string = ' - '; private _reverse: boolean = false; - private destroy$ = new Subject(); private tit$?: Subscription; readonly DELAY_TIME = 25; @@ -34,7 +35,7 @@ export class TitleService implements OnDestroy { private i18nSrv: AlainI18NService, @Inject(DOCUMENT) private doc: NzSafeAny ) { - this.i18nSrv.change.pipe(takeUntil(this.destroy$)).subscribe(() => this.setTitle()); + i18nSrv.change.pipe(takeUntilDestroyed()).subscribe(() => this.setTitle()); } /** @@ -138,7 +139,7 @@ export class TitleService implements OnDestroy { switchMap(tit => (tit ? of(tit) : this.getByElement())), map(tit => tit || this.default), map(title => (!Array.isArray(title) ? [title] : title)), - takeUntil(this.destroy$) + takeUntilDestroyed(this.destroy$) ) .subscribe(titles => { let newTitles: string[] = []; @@ -165,7 +166,5 @@ export class TitleService implements OnDestroy { ngOnDestroy(): void { this.tit$?.unsubscribe(); - this.destroy$.next(); - this.destroy$.complete(); } } diff --git a/packages/theme/theme-btn/theme-btn.component.ts b/packages/theme/theme-btn/theme-btn.component.ts index 500a95c660..e010f24406 100644 --- a/packages/theme/theme-btn/theme-btn.component.ts +++ b/packages/theme/theme-btn/theme-btn.component.ts @@ -3,6 +3,7 @@ import { Platform } from '@angular/cdk/platform'; import { DOCUMENT } from '@angular/common'; import { ChangeDetectionStrategy, + ChangeDetectorRef, Component, EventEmitter, Inject, @@ -15,7 +16,7 @@ import { Output, Renderer2 } from '@angular/core'; -import { Subject, takeUntil } from 'rxjs'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { AlainConfigService } from '@delon/util/config'; import type { NzSafeAny } from 'ng-zorro-antd/core/types'; @@ -47,7 +48,7 @@ export class ThemeBtnComponent implements OnInit, OnDestroy { @Input() devTips = `When the dark.css file can't be found, you need to run it once: npm run theme`; @Input() deployUrl = ''; @Output() readonly themeChange = new EventEmitter(); - private destroy$ = new Subject(); + private dir$ = this.directionality.change?.pipe(takeUntilDestroyed()); dir: Direction = 'ltr'; constructor( @@ -56,13 +57,15 @@ export class ThemeBtnComponent implements OnInit, OnDestroy { private platform: Platform, @Inject(DOCUMENT) private doc: NzSafeAny, @Optional() private directionality: Directionality, - @Inject(ALAIN_THEME_BTN_KEYS) private KEYS: string + @Inject(ALAIN_THEME_BTN_KEYS) private KEYS: string, + private cdr: ChangeDetectorRef ) {} ngOnInit(): void { this.dir = this.directionality.value; - this.directionality.change?.pipe(takeUntil(this.destroy$)).subscribe((direction: Direction) => { + this.dir$.subscribe((direction: Direction) => { this.dir = direction; + this.cdr.detectChanges(); }); this.initTheme(); } @@ -110,7 +113,5 @@ export class ThemeBtnComponent implements OnInit, OnDestroy { if (el != null) { this.doc.body.removeChild(el); } - this.destroy$.next(); - this.destroy$.complete(); } } diff --git a/src/app/layout/layout.component.ts b/src/app/layout/layout.component.ts index 791d2b240a..70b3428964 100644 --- a/src/app/layout/layout.component.ts +++ b/src/app/layout/layout.component.ts @@ -1,7 +1,8 @@ import { Location } from '@angular/common'; -import { Component, OnDestroy } from '@angular/core'; +import { Component } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { NavigationEnd, NavigationError, RouteConfigLoadStart, Router } from '@angular/router'; -import { Subject, delay, filter, takeUntil } from 'rxjs'; +import { delay, filter } from 'rxjs'; import { RTL, RTLService, SettingsService } from '@delon/theme'; import { NzMessageService } from 'ng-zorro-antd/message'; @@ -23,8 +24,7 @@ import { AppService, SiteTheme } from '../core/app.service'; '[attr.id]': `'ng-content'` } }) -export class LayoutComponent implements OnDestroy { - private destroy$ = new Subject(); +export class LayoutComponent { isFetching = false; render = true; @@ -37,7 +37,7 @@ export class LayoutComponent implements OnDestroy { private appSrv: AppService ) { rtl.change.subscribe(() => this.fixDirection()); - router.events.pipe(takeUntil(this.destroy$)).subscribe(evt => { + router.events.pipe(takeUntilDestroyed()).subscribe(evt => { if (!this.isFetching && evt instanceof RouteConfigLoadStart) { this.isFetching = true; } @@ -53,7 +53,7 @@ export class LayoutComponent implements OnDestroy { }); router.events .pipe( - takeUntil(this.destroy$), + takeUntilDestroyed(), filter(ev => ev instanceof NavigationEnd), delay(100) ) @@ -79,10 +79,4 @@ export class LayoutComponent implements OnDestroy { themeChange(theme: string): void { this.appSrv.setTheme(theme as SiteTheme); } - - ngOnDestroy(): void { - const { destroy$ } = this; - destroy$.next(); - destroy$.complete(); - } } diff --git a/src/app/routes/form-pages/validator/validator.component.ts b/src/app/routes/form-pages/validator/validator.component.ts index b0de3bbfb2..ca130d0c63 100644 --- a/src/app/routes/form-pages/validator/validator.component.ts +++ b/src/app/routes/form-pages/validator/validator.component.ts @@ -1,13 +1,5 @@ -import { - ChangeDetectionStrategy, - ChangeDetectorRef, - Component, - Inject, - OnDestroy, - OnInit, - ViewChild -} from '@angular/core'; -import { Subject, takeUntil } from 'rxjs'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, OnInit, ViewChild } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { NuMonacoEditorComponent } from '@ng-util/monaco-editor'; @@ -59,12 +51,11 @@ export class DemoComponent { templateUrl: './validator.component.html', changeDetection: ChangeDetectionStrategy.OnPush }) -export class FormValidatorComponent implements OnInit, OnDestroy { +export class FormValidatorComponent implements OnInit { @ViewChild('schemaEditor') private schemaEditor!: NuMonacoEditorComponent; @ViewChild('formCodeEditor') private formCodeEditor!: NuMonacoEditorComponent; @ViewChild('uiEditor') private uiEditor!: NuMonacoEditorComponent; - private destroy$ = new Subject(); files: Array<{ name: string; title: string; cache?: string }> = [ { name: 'basic', title: '基本' }, { name: 'conditional', title: '条件' }, @@ -95,7 +86,7 @@ export class FormValidatorComponent implements OnInit, OnDestroy { const defaultIndex = 0; this.name = this.files[defaultIndex].name; this.title = this.files[defaultIndex].title; - this.appService.theme$.pipe(takeUntil(this.destroy$)).subscribe(data => { + this.appService.theme$.pipe(takeUntilDestroyed()).subscribe(data => { this.editorOptions = { language: 'json', theme: data === 'dark' ? 'vs-dark' : 'vs' }; }); } @@ -167,9 +158,4 @@ export class FormValidatorComponent implements OnInit, OnDestroy { error(value: NzSafeAny): void { console.log('formError', value); } - - ngOnDestroy(): void { - this.destroy$.next(); - this.destroy$.complete(); - } } diff --git a/src/app/shared/components/code-box/code-box.component.ts b/src/app/shared/components/code-box/code-box.component.ts index bada29ef84..ff7d73ee2a 100644 --- a/src/app/shared/components/code-box/code-box.component.ts +++ b/src/app/shared/components/code-box/code-box.component.ts @@ -1,7 +1,17 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, Input, OnDestroy, OnInit } from '@angular/core'; +import { + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + DestroyRef, + Inject, + Input, + OnInit, + inject +} from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { DomSanitizer } from '@angular/platform-browser'; -import { Subject, filter, takeUntil } from 'rxjs'; +import { filter } from 'rxjs'; import { ALAIN_I18N_TOKEN } from '@delon/theme'; import { copy } from '@delon/util/browser'; @@ -19,10 +29,10 @@ import { AppService, CodeService, I18NService } from '@core'; }, changeDetection: ChangeDetectionStrategy.OnPush }) -export class CodeBoxComponent implements OnInit, OnDestroy { +export class CodeBoxComponent implements OnInit { private _item: any; private _orgItem: any; - private destroy$ = new Subject(); + private destroy$ = inject(DestroyRef); copied = false; theme = 'default'; @@ -58,14 +68,14 @@ export class CodeBoxComponent implements OnInit, OnDestroy { ) {} ngOnInit(): void { - this.appService.theme$.pipe(takeUntil(this.destroy$)).subscribe(data => { + this.appService.theme$.pipe(takeUntilDestroyed(this.destroy$)).subscribe(data => { this.theme = data; this.check(); }); this.i18n.change .pipe( filter(() => !!this._orgItem), - takeUntil(this.destroy$) + takeUntilDestroyed(this.destroy$) ) .subscribe(() => { this.item.title = this.i18n.get(this._orgItem.meta.title); @@ -103,9 +113,4 @@ export class CodeBoxComponent implements OnInit, OnDestroy { }, 1000); }); } - - ngOnDestroy(): void { - this.destroy$.next(); - this.destroy$.complete(); - } } diff --git a/src/app/shared/components/content/content.component.ts b/src/app/shared/components/content/content.component.ts index 8aec358f35..df94f81c66 100644 --- a/src/app/shared/components/content/content.component.ts +++ b/src/app/shared/components/content/content.component.ts @@ -1,5 +1,5 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; -import { Subject, takeUntil } from 'rxjs'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, DestroyRef, OnInit, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MetaService, MobileService } from '@core'; @@ -11,8 +11,8 @@ import { MetaService, MobileService } from '@core'; }, changeDetection: ChangeDetectionStrategy.OnPush }) -export class ContentComponent implements OnInit, OnDestroy { - private destroy$ = new Subject(); +export class ContentComponent implements OnInit { + private destroy$ = inject(DestroyRef); isMobile!: boolean; opened = false; @@ -23,7 +23,7 @@ export class ContentComponent implements OnInit, OnDestroy { ) {} ngOnInit(): void { - this.mobileSrv.change.pipe(takeUntil(this.destroy$)).subscribe(res => { + this.mobileSrv.change.pipe(takeUntilDestroyed(this.destroy$)).subscribe(res => { this.isMobile = res; this.cdr.detectChanges(); }); @@ -32,10 +32,4 @@ export class ContentComponent implements OnInit, OnDestroy { to(): void { this.opened = false; } - - ngOnDestroy(): void { - const { destroy$ } = this; - destroy$.next(); - destroy$.complete(); - } } diff --git a/src/app/shared/components/main-menu/main-menu.component.ts b/src/app/shared/components/main-menu/main-menu.component.ts index 71f190e3da..b2bf6e977f 100644 --- a/src/app/shared/components/main-menu/main-menu.component.ts +++ b/src/app/shared/components/main-menu/main-menu.component.ts @@ -2,13 +2,14 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + DestroyRef, EventEmitter, Inject, - OnDestroy, OnInit, - Output + Output, + inject } from '@angular/core'; -import { Subject, takeUntil } from 'rxjs'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ALAIN_I18N_TOKEN } from '@delon/theme'; import type { NzSafeAny } from 'ng-zorro-antd/core/types'; @@ -20,8 +21,8 @@ import { I18NService, MetaService } from '@core'; templateUrl: './main-menu.component.html', changeDetection: ChangeDetectionStrategy.OnPush }) -export class MainMenuComponent implements OnInit, OnDestroy { - private destroy$ = new Subject(); +export class MainMenuComponent implements OnInit { + private destroy$ = inject(DestroyRef); count = 0; @Output() readonly to = new EventEmitter(); @@ -37,13 +38,7 @@ export class MainMenuComponent implements OnInit, OnDestroy { ) {} ngOnInit(): void { - this.i18n.change.pipe(takeUntil(this.destroy$)).subscribe(() => this.cdr.markForCheck()); + this.i18n.change.pipe(takeUntilDestroyed(this.destroy$)).subscribe(() => this.cdr.markForCheck()); this.count = this.meta.menus?.reduce((p: number, c: NzSafeAny) => (p += c.list.length), 0); } - - ngOnDestroy(): void { - const { destroy$ } = this; - destroy$.next(); - destroy$.complete(); - } }