При реализации модального окна с использованием ng-content (content projection) возникает критичная проблема: контент переданный в неё затирается. Сейчас модалка сразу же открывается при входе в приложение и только в этот момент данные отображаются(для дебага)
Как должно работать:
Пользователь жмет кнопку
Открывается модалка с контентом переданным в нее(любая форма)
Суть в том, что через ng-content можно было бы отправлять в модалку компоненты или html, эдакий конструктор.
Реализация сейчас:
service:
export class ModalService {
containerModal?: ViewContainerRef;
modalRef?: ComponentRef<any>;
registerModalContainer(container: ViewContainerRef): void {
this.containerModal = container;
}
show(component: any) {
if (!this.containerModal) return;
this.modalRef = this.containerModal.createComponent(component);
}
destroy(): void {
if (this.modalRef) {
this.modalRef.destroy();
}
}
}
модалка:
export class ModalService {
containerModal?: ViewContainerRef;
modalRef?: ComponentRef<any>;
registerModalContainer(container: ViewContainerRef): void {
this.containerModal = container;
}
show(component: any) {
if (!this.containerModal) return;
this.modalRef = this.containerModal.createComponent(component);
}
destroy(): void {
if (this.modalRef) {
this.modalRef.destroy();
}
}
}
@if (close()){
<div class="overlay">
<div class="window_modal" >
<button class="clear_btn" (click)="onClose()">
<svg icon="cross" class="svg10"></svg>
</button>
<ng-content>
</ng-content>
</div>
</div>}
Host:
@Component({
selector: 'tt-host-modal',
imports: [],
templateUrl: `/host-modal.component.html`,
styleUrl: './host-modal.component.scss',
})
export class HostModalComponent implements AfterViewInit, OnDestroy {
@ViewChild('modalHost', { read: ViewContainerRef })
containerRef?: ViewContainerRef;
modalService = inject(ModalService);
ngAfterViewInit(): void {
if (!this.containerRef) {return;}
this.modalService.registerModalContainer(this.containerRef)
}
ngOnDestroy(): void {
this.modalService.destroy();
}}
<ng-template #modalHost></ng-template>
страница с модалкой:
@Component({
selector: 'tt-community-page',
imports: [
CommunityCardComponent,
CommunityFiltersComponent,
SvgIconComponent,
InfiniteScrollTriggerComponent,
WindowModalComponent,
],
templateUrl: './community-page.component.html',
styleUrl: './community-page.component.scss',
})
export class CommunityPageComponent {
#store = inject(Store);
modalService = inject(ModalService);
communities$ = this.#store.selectSignal(communityFeature.selectCommunityFiltered);
timeToFetch() {
this.#store.dispatch(filtercommunityActions.setPage({ page: 1 }));
}
createCommunityModal(): void {
this.modalService.show(WindowModalComponent)
}
}
<code lang="html">
<div class="btn-wrapper">
<h1>Cообщества</h1>
<button class="btn" (click)="createCommunityModal()">Создать сообщество
<svg icon="content" class="svg16 "></svg>
</button>
</div>
<tt-window-modal>
Habr
</tt-window-modal>
<tt-community-filters></tt-community-filters>
<div class="wrapper-for">
@for (community of communities$(); track community.id; let last = $last) {
<tt-community-card [community]="community"></tt-community-card>
@if (last) {
@defer (on viewport) {
<tt-infinite-scroll-trigger
(loaded)="timeToFetch()"
></tt-infinite-scroll-trigger>
} @placeholder {
<div></div>
}
}
}
</div>
</code>