All files / modal/components modal-container.component.ts

100% Statements 23/23
100% Branches 0/0
100% Functions 3/3
100% Lines 22/22

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 693x 3x   3x                   3x 3x                           3x 3x 3x 3x 3x   3x       3x     3x       3x 3x   2x   1x     2x         2x     2x   1x 1x        
import { SpinnerComponent } from '../../components/spinner/spinner.component';
import { MODAL_DATA } from '../models/modal.tokens';
import { LazyComponentLoader, ModalData } from '../models/modal.types';
import {
    AfterViewInit,
    ChangeDetectionStrategy,
    Component,
    Injector,
    ViewContainerRef,
    inject,
    signal,
    viewChild,
} from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { LoggerService } from '@drevo-web/core';
 
interface LazyModalData<TData = unknown> {
    loader: LazyComponentLoader<unknown>;
    data: TData;
}
 
@Component({
    selector: 'ui-modal-container',
    imports: [SpinnerComponent],
    templateUrl: 'modal-container.component.html',
    styleUrl: './modal-container.component.scss',
    changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ModalContainerComponent<TData = unknown, TResult = unknown> implements AfterViewInit {
    private readonly dialogRef = inject<MatDialogRef<ModalContainerComponent<TData, TResult>, TResult>>(MatDialogRef);
    private readonly dialogData = inject<LazyModalData<TData>>(MAT_DIALOG_DATA);
    private readonly injector = inject(Injector);
    private readonly logger = inject(LoggerService).withContext('ModalContainerComponent');
 
    private readonly outlet = viewChild.required('outlet', {
        read: ViewContainerRef,
    });
 
    protected readonly isLoading = signal(true);
 
    ngAfterViewInit(): void {
        this.loadComponent();
    }
 
    private async loadComponent(): Promise<void> {
        try {
            const componentType = await this.dialogData.loader();
 
            const modalData: ModalData<TData, TResult> = {
                data: this.dialogData.data,
                close: (result?: TResult) => this.dialogRef.close(result),
            };
 
            const injector = Injector.create({
                providers: [{ provide: MODAL_DATA, useValue: modalData }],
                parent: this.injector,
            });
 
            this.outlet().createComponent(componentType, {
                injector,
            });
            this.isLoading.set(false);
        } catch (error) {
            this.logger.error('Failed to load modal component:', error);
            this.dialogRef.close();
        }
    }
}