diff --git a/npm/ng-packs/apps/dev-app/src/app/dynamic-form-page/dynamic-form-page.component.ts b/npm/ng-packs/apps/dev-app/src/app/dynamic-form-page/dynamic-form-page.component.ts index 0955a448e5..aaa213775c 100644 --- a/npm/ng-packs/apps/dev-app/src/app/dynamic-form-page/dynamic-form-page.component.ts +++ b/npm/ng-packs/apps/dev-app/src/app/dynamic-form-page/dynamic-form-page.component.ts @@ -1,4 +1,4 @@ -import { Component, inject, OnInit, ViewChild } from '@angular/core'; +import { Component, inject, OnInit, viewChild } from '@angular/core'; import { DynamicFormComponent, FormFieldConfig } from '@abp/ng.components/dynamic-form'; import { FormConfigService } from './form-config.service'; @@ -8,7 +8,7 @@ import { FormConfigService } from './form-config.service'; imports: [DynamicFormComponent], }) export class DynamicFormPageComponent implements OnInit { - @ViewChild(DynamicFormComponent, { static: false }) dynamicFormComponent: DynamicFormComponent; + readonly dynamicFormComponent = viewChild(DynamicFormComponent); protected readonly formConfigService = inject(FormConfigService); formFields: FormFieldConfig[] = []; @@ -27,12 +27,12 @@ export class DynamicFormPageComponent implements OnInit { alert('✅ Form submitted successfully! Check the console for details.'); // Reset form after submission - this.dynamicFormComponent.resetForm(); + this.dynamicFormComponent().resetForm(); } cancel() { console.log('❌ Form Cancelled'); alert('Form cancelled'); - this.dynamicFormComponent.resetForm(); + this.dynamicFormComponent().resetForm(); } } diff --git a/npm/ng-packs/packages/components/dynamic-form/src/dynamic-form-field/dynamic-form-field-host.component.ts b/npm/ng-packs/packages/components/dynamic-form/src/dynamic-form-field/dynamic-form-field-host.component.ts index 56f32f6e0d..d711b2030a 100644 --- a/npm/ng-packs/packages/components/dynamic-form/src/dynamic-form-field/dynamic-form-field-host.component.ts +++ b/npm/ng-packs/packages/components/dynamic-form/src/dynamic-form-field/dynamic-form-field-host.component.ts @@ -1,6 +1,5 @@ import { Component, - ViewChild, ViewContainerRef, ChangeDetectionStrategy, forwardRef, @@ -9,6 +8,7 @@ import { DestroyRef, inject, input, + viewChild } from '@angular/core'; import { ControlValueAccessor, NG_VALUE_ACCESSOR, FormControl, ReactiveFormsModule @@ -34,7 +34,7 @@ export class DynamicFieldHostComponent implements ControlValueAccessor { component = input>(); inputs = input>({}); - @ViewChild('vcRef', { read: ViewContainerRef, static: true }) viewContainerRef!: ViewContainerRef; + readonly viewContainerRef = viewChild.required('vcRef', { read: ViewContainerRef }); private componentRef?: any; private value: any; @@ -55,10 +55,10 @@ export class DynamicFieldHostComponent implements ControlValueAccessor { } private createChild() { - this.viewContainerRef.clear(); + this.viewContainerRef().clear(); if (!this.component()) return; - this.componentRef = this.viewContainerRef.createComponent(this.component()); + this.componentRef = this.viewContainerRef().createComponent(this.component()); this.applyInputs(); const instance: any = this.componentRef.instance as controlValueAccessorLike & acceptsFormControl; diff --git a/npm/ng-packs/packages/components/extensible/src/lib/components/date-time-picker/extensible-date-time-picker.component.ts b/npm/ng-packs/packages/components/extensible/src/lib/components/date-time-picker/extensible-date-time-picker.component.ts index 907118283e..05fad7a63d 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/components/date-time-picker/extensible-date-time-picker.component.ts +++ b/npm/ng-packs/packages/components/extensible/src/lib/components/date-time-picker/extensible-date-time-picker.component.ts @@ -6,7 +6,7 @@ import { input, Optional, SkipSelf, - ViewChild, + viewChild } from '@angular/core'; import { ControlContainer, ReactiveFormsModule } from '@angular/forms'; import { @@ -76,14 +76,14 @@ export class ExtensibleDateTimePickerComponent { meridian = input(false); placement = input('bottom-left'); - @ViewChild(NgbInputDatepicker) date!: NgbInputDatepicker; - @ViewChild(NgbTimepicker) time!: NgbTimepicker; + readonly date = viewChild.required(NgbInputDatepicker); + readonly time = viewChild.required(NgbTimepicker); setDate(dateStr: string) { - this.date.writeValue(dateStr); + this.date().writeValue(dateStr); } setTime(dateStr: string) { - this.time.writeValue(dateStr); + this.time().writeValue(dateStr); } } diff --git a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form-prop.component.ts b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form-prop.component.ts index 09a29a98a9..db7c0636b8 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form-prop.component.ts +++ b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form-prop.component.ts @@ -19,9 +19,7 @@ import { Optional, SimpleChanges, SkipSelf, - ViewChild, - signal, - effect, + viewChild, } from '@angular/core'; import { ControlContainer, @@ -72,8 +70,8 @@ import { ExtensibleFormMultiselectComponent } from '../multi-select/extensible-f AsyncPipe, NgComponentOutlet, NgTemplateOutlet, - FormsModule -], + FormsModule, + ], changeDetection: ChangeDetectionStrategy.OnPush, providers: [ExtensibleFormPropService], viewProviders: [ @@ -98,7 +96,7 @@ export class ExtensibleFormPropComponent implements OnChanges, AfterViewInit { @Input() prop!: FormProp; @Input() first?: boolean; @Input() isFirstGroup?: boolean; - @ViewChild('field') private fieldRef!: ElementRef; + private readonly fieldRef = viewChild.required>('field'); injectorForCustomComponent?: Injector; asterisk = ''; @@ -158,9 +156,9 @@ export class ExtensibleFormPropComponent implements OnChanges, AfterViewInit { } ngAfterViewInit() { - if (this.isFirstGroup && this.first && this.fieldRef) { + if (this.isFirstGroup && this.first && this.fieldRef()) { requestAnimationFrame(() => { - this.fieldRef.nativeElement.focus(); + this.fieldRef().nativeElement.focus(); }); } } diff --git a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form.component.ts b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form.component.ts index 8b5829754d..4da4a21468 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form.component.ts +++ b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form.component.ts @@ -6,9 +6,8 @@ import { inject, Input, Optional, - QueryList, SkipSelf, - ViewChildren, + viewChildren } from '@angular/core'; import { ControlContainer, ReactiveFormsModule, UntypedFormGroup } from '@angular/forms'; import { EXTRA_PROPERTIES_KEY } from '../../constants/extra-properties'; @@ -41,8 +40,7 @@ export class ExtensibleFormComponent { private readonly extensions = inject(ExtensionsService); private readonly identifier = inject(EXTENSIONS_IDENTIFIER); - @ViewChildren(ExtensibleFormPropComponent) - formProps!: QueryList; + readonly formProps = viewChildren(ExtensibleFormPropComponent); @Input() set selectedRecord(record: R) { 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..8669982c9c 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 @@ -4,7 +4,6 @@ import { ChangeDetectorRef, Component, computed, - ContentChild, EventEmitter, inject, Injector, @@ -18,7 +17,8 @@ import { SimpleChanges, TemplateRef, TrackByFunction, - ViewChild, + contentChild, + viewChild } from '@angular/core'; import { AsyncPipe, isPlatformBrowser, NgComponentOutlet, NgTemplateOutlet } from '@angular/common'; @@ -141,17 +141,16 @@ export class ExtensibleTableComponent implements OnChanges, AfterViewIn @Input() rowDetailHeight: string | number = '100%'; @Output() rowDetailToggle = new EventEmitter(); - @ContentChild(ExtensibleTableRowDetailComponent) - rowDetailComponent?: ExtensibleTableRowDetailComponent; + readonly rowDetailComponent = contentChild(ExtensibleTableRowDetailComponent); - @ViewChild('table', { static: false }) table!: DatatableComponent; + readonly table = viewChild.required('table'); protected get effectiveRowDetailTemplate(): TemplateRef> | undefined { - return this.rowDetailComponent?.template() ?? this.rowDetailTemplate; + return this.rowDetailComponent()?.template() ?? this.rowDetailTemplate; } protected get effectiveRowDetailHeight(): string | number { - return this.rowDetailComponent?.rowHeight() ?? this.rowDetailHeight; + return this.rowDetailComponent()?.rowHeight() ?? this.rowDetailHeight; } hasAtLeastOnePermittedAction: boolean; @@ -318,8 +317,9 @@ export class ExtensibleTableComponent implements OnChanges, AfterViewIn } toggleExpandRow(row: R): void { - if (this.table && this.table.rowDetail) { - this.table.rowDetail.toggleExpandRow(row); + const table = this.table(); + if (table && table.rowDetail) { + table.rowDetail.toggleExpandRow(row); } this.rowDetailToggle.emit(row); } diff --git a/npm/ng-packs/packages/components/page/src/page.component.html b/npm/ng-packs/packages/components/page/src/page.component.html index ee32f2e5e2..1f33a841f4 100644 --- a/npm/ng-packs/packages/components/page/src/page.component.html +++ b/npm/ng-packs/packages/components/page/src/page.component.html @@ -1,6 +1,6 @@ @if (shouldRenderRow) {
- @if (customTitle) { + @if (customTitle()) { } @else { @if (title) { @@ -12,7 +12,7 @@ } } - @if (customBreadcrumb) { + @if (customBreadcrumb()) { } @else { @if (breadcrumb) { @@ -22,7 +22,7 @@ } } - @if (customToolbar) { + @if (customToolbar()) { } @else { @if (toolbarVisible) { diff --git a/npm/ng-packs/packages/components/page/src/page.component.ts b/npm/ng-packs/packages/components/page/src/page.component.ts index bd5242651f..da81504e79 100644 --- a/npm/ng-packs/packages/components/page/src/page.component.ts +++ b/npm/ng-packs/packages/components/page/src/page.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, ViewEncapsulation, ContentChild } from '@angular/core'; +import { Component, Input, ViewEncapsulation, contentChild } from '@angular/core'; import { PageTitleContainerComponent, PageBreadcrumbContainerComponent, @@ -37,19 +37,18 @@ export class PageComponent { toolbar: PageParts.toolbar, }; - @ContentChild(PageTitleContainerComponent) customTitle?: PageTitleContainerComponent; - @ContentChild(PageBreadcrumbContainerComponent) - customBreadcrumb?: PageBreadcrumbContainerComponent; - @ContentChild(PageToolbarContainerComponent) customToolbar?: PageToolbarContainerComponent; + readonly customTitle = contentChild(PageTitleContainerComponent); + readonly customBreadcrumb = contentChild(PageBreadcrumbContainerComponent); + readonly customToolbar = contentChild(PageToolbarContainerComponent); get shouldRenderRow() { return !!( this.title || this.toolbarVisible || this.breadcrumb || - this.customTitle || - this.customBreadcrumb || - this.customToolbar || + this.customTitle() || + this.customBreadcrumb() || + this.customToolbar() || this.pageParts ); } diff --git a/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.html b/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.html index 8cd2058699..2dbe164d01 100644 --- a/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.html +++ b/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.html @@ -7,7 +7,7 @@ [nzData]="nodes" [nzTreeTemplate]="treeTemplate" [nzExpandedKeys]="expandedKeys" - [nzExpandedIcon]="expandedIconTemplate?.template || defaultIconTemplate" + [nzExpandedIcon]="expandedIconTemplate()?.template || defaultIconTemplate" (nzExpandChange)="onExpandedKeysChange($event)" (nzCheckboxChange)="onCheckboxChange($event)" (nzOnDrop)="onDrop($event)" @@ -26,13 +26,13 @@
- @if (menu) { + @if (menu()) { } diff --git a/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.ts b/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.ts index 5c320a539b..97e0f305d6 100644 --- a/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.ts +++ b/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.ts @@ -2,7 +2,7 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, - ContentChild, + contentChild, EventEmitter, inject, Input, @@ -60,9 +60,9 @@ export class TreeComponent implements OnInit { dropdowns = {} as { [key: string]: NgbDropdown }; - @ContentChild('menu') menu: TemplateRef; - @ContentChild(TreeNodeTemplateDirective) customNodeTemplate: TreeNodeTemplateDirective; - @ContentChild(ExpandedIconTemplateDirective) expandedIconTemplate: ExpandedIconTemplateDirective; + readonly menu = contentChild>('menu'); + readonly customNodeTemplate = contentChild(TreeNodeTemplateDirective); + readonly expandedIconTemplate = contentChild(ExpandedIconTemplateDirective); @Output() readonly checkedKeysChange = new EventEmitter(); @Output() readonly expandedKeysChange = new EventEmitter(); @Output() readonly selectedNodeChange = new EventEmitter(); diff --git a/npm/ng-packs/packages/identity/src/lib/components/users/users.component.ts b/npm/ng-packs/packages/identity/src/lib/components/users/users.component.ts index 7ff04cf679..ada580059d 100644 --- a/npm/ng-packs/packages/identity/src/lib/components/users/users.component.ts +++ b/npm/ng-packs/packages/identity/src/lib/components/users/users.component.ts @@ -39,7 +39,7 @@ import { OnInit, TemplateRef, TrackByFunction, - ViewChild, + viewChild } from '@angular/core'; import { AbstractControl, @@ -99,8 +99,7 @@ export class UsersComponent implements OnInit { data: PagedResultDto = { items: [], totalCount: 0 }; - @ViewChild('modalContent', { static: false }) - modalContent!: TemplateRef; + readonly modalContent = viewChild.required>('modalContent'); form!: UntypedFormGroup; 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..635f5ed86b 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 @@ -15,21 +15,22 @@ import { UpdatePermissionDto, } from '@abp/ng.permission-management/proxy'; import { + afterNextRender, Component, computed, DOCUMENT, ElementRef, EventEmitter, inject, + Injector, Input, Output, - QueryList, signal, TrackByFunction, - ViewChildren, + viewChildren } from '@angular/core'; -import { concat, of } from 'rxjs'; -import { finalize, switchMap, take, tap } from 'rxjs/operators'; +import { of } from 'rxjs'; +import { finalize, switchMap, tap } from 'rxjs/operators'; import { PermissionManagement } from '../models'; import { FormsModule } from '@angular/forms'; @@ -116,6 +117,7 @@ export class PermissionManagementComponent protected readonly service = inject(PermissionsService); protected readonly configState = inject(ConfigStateService); protected readonly toasterService = inject(ToasterService); + private readonly injector = inject(Injector); private document = inject(DOCUMENT); @Input() @@ -146,11 +148,9 @@ export class PermissionManagementComponent this.openModal().subscribe(() => { this._visible = true; this.visibleChange.emit(true); - concat(this.selectAllInAllTabsRef.changes, this.selectAllInThisTabsRef.changes) - .pipe(take(1)) - .subscribe(() => { - this.initModal(); - }); + afterNextRender(() => { + this.initModal(); + }, { injector: this.injector }); }); } else { this.setSelectedGroup(null); @@ -162,10 +162,8 @@ export class PermissionManagementComponent @Output() readonly visibleChange = new EventEmitter(); - @ViewChildren('selectAllInThisTabsRef') - selectAllInThisTabsRef!: QueryList>; - @ViewChildren('selectAllInAllTabsRef') - selectAllInAllTabsRef!: QueryList>; + selectAllInThisTabsRef = viewChildren>('selectAllInThisTabsRef'); + selectAllInAllTabsRef = viewChildren>('selectAllInAllTabsRef'); data: GetPermissionListResultDto = { groups: [], entityDisplayName: '' }; diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.ts b/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.ts index a6afd37b12..40782d113c 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.ts +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.ts @@ -11,10 +11,9 @@ import { ElementRef, inject, Input, - QueryList, Renderer2, TrackByFunction, - ViewChildren, + viewChildren } from '@angular/core'; import { NgTemplateOutlet, AsyncPipe } from '@angular/common'; import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'; @@ -41,7 +40,7 @@ export class RoutesComponent { @Input() smallScreen?: boolean; - @ViewChildren('childrenContainer') childrenContainers!: QueryList>; + readonly childrenContainers = viewChildren>('childrenContainer'); rootDropdownExpand = {} as { [key: string]: boolean }; @@ -52,7 +51,7 @@ export class RoutesComponent { } closeDropdown() { - this.childrenContainers.forEach(({ nativeElement }) => { + this.childrenContainers().forEach(({ nativeElement }) => { this.renderer.addClass(nativeElement, 'd-none'); setTimeout(() => this.renderer.removeClass(nativeElement, 'd-none'), 0); }); 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..cd717d1a2d 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 @@ -7,8 +7,8 @@ import { OnInit, Output, Renderer2, - ViewChild, inject, + viewChild } from '@angular/core'; import { ABP, StopPropagationDirective } from '@abp/ng.core'; @@ -70,8 +70,7 @@ export class ButtonComponent implements OnInit { @Output() readonly abpBlur = new EventEmitter(); - @ViewChild('button', { static: true }) - buttonRef!: ElementRef; + readonly buttonRef = viewChild.required>('button'); get icon(): string { return `${this.loading ? 'fa fa-spinner fa-spin' : this.iconClass || 'd-none'}`; @@ -81,7 +80,7 @@ export class ButtonComponent implements OnInit { if (this.attributes) { Object.keys(this.attributes).forEach(key => { if (this.attributes?.[key]) { - this.renderer.setAttribute(this.buttonRef.nativeElement, key, this.attributes[key]); + this.renderer.setAttribute(this.buttonRef().nativeElement, key, this.attributes[key]); } }); } diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/http-error-wrapper/http-error-wrapper.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/http-error-wrapper/http-error-wrapper.component.ts index 24e7fae1d6..c24728b886 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/http-error-wrapper/http-error-wrapper.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/http-error-wrapper/http-error-wrapper.component.ts @@ -6,12 +6,12 @@ import { ElementRef, EmbeddedViewRef, Type, - ViewChild, AfterViewInit, OnDestroy, createComponent, EnvironmentInjector, DestroyRef, + viewChild } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { DOCUMENT } from '@angular/common'; @@ -53,8 +53,7 @@ export class HttpErrorWrapperComponent implements OnInit, AfterViewInit, OnDestr isHomeShow = true; - @ViewChild('container', { static: false }) - containerRef?: ElementRef; + readonly containerRef = viewChild>('container'); get statusText(): string { return this.status ? `[${this.status}]` : ''; @@ -86,8 +85,9 @@ export class HttpErrorWrapperComponent implements OnInit, AfterViewInit, OnDestr this.appRef.attachView(customComponentRef.hostView); - if (this.containerRef) { - this.containerRef.nativeElement.appendChild( + const containerRef = this.containerRef(); + if (containerRef) { + containerRef.nativeElement.appendChild( (customComponentRef.hostView as EmbeddedViewRef).rootNodes[0], ); }