import { Injectable, Type } from '@angular/core';
import { Subject } from 'rxjs';
export type CreateSidebarOptions = {
component: Type<any>;
componentProps?: any;
};
@Injectable({
providedIn: 'root',
})
export class SidebarService {
open$: Subject<CreateSidebarOptions> = new Subject<CreateSidebarOptions>();
close$: Subject<void> = new Subject<void>();
constructor() {}
async open(data: CreateSidebarOptions) {
this.open$.next(data);
}
dismiss() {
this.close$.next();
}
}
- 서비스를 활용하여 핸들링하겠습니다.
<ion-menu
side="end"
contentId="main"
(ionDidClose)="onClose()"
swipeGesture="false"
>
<div class="flex flex-col h-full gap-6 p-4">
<app-icon
class="cursor-pointer w-7 h-7 hover:text-gray-300"
name="material-symbols:keyboard-double-arrow-right"
(click)="close()"
/>
<ng-template #container />
</div>
</ion-menu>
- sidebar 템플릿
import {
Component,
OnDestroy,
ViewChild,
ViewContainerRef,
OnInit,
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { IonMenu, IonicModule } from '@ionic/angular';
import {
SidebarService,
CreateSidebarOptions,
} from '../../../services/sidebar.service';
import { IconComponent } from '@common/lib';
@Component({
selector: 'app-sidebar',
standalone: true,
imports: [CommonModule, IonicModule, IconComponent],
templateUrl: './sidebar.component.html',
styleUrls: ['./sidebar.component.scss'],
})
export class SidebarComponent implements OnInit, OnDestroy {
@ViewChild(IonMenu) menu!: IonMenu;
@ViewChild('container', { read: ViewContainerRef })
container!: ViewContainerRef;
constructor(private readonly sidebarService: SidebarService) {
this.sidebarService.open$.subscribe({
next: (component) => {
this.show(component);
},
});
}
ngOnInit(): void {
this.sidebarService.close$.subscribe({
next: (data) => {
this.close();
},
});
}
show(data: CreateSidebarOptions) {
const { component, componentProps } = data;
const createdComponent = this.container.createComponent(component, {});
if (componentProps) {
Object.assign(createdComponent.instance, componentProps);
}
this.menu.open();
}
close() {
this.menu.close();
this.onClose();
}
onClose() {
this.container.clear();
}
ngOnDestroy(): void {
this.container.clear();
}
}
- sidebar 컴포넌트
<ion-content id="content">
<section class="flex w-full h-full select-none">
<app-aside />
<div class="flex flex-col w-full">
<app-header />
<router-outlet></router-outlet>
</div>
<app-sidebar />
</section>
</ion-content>
- Layout 템플릿
constructor(
private readonly sidebarService: SidebarService,
) {}
async sideToggle(page: any) {
await this.sidebarService.open({
component: component,
componentProps: { result: this.result },
});
this.sidebarService.close$.subscribe({
next: (data) => {
this.getItem();
},
});
}
- 메뉴를 여는 컴포넌트 내부
<app-button
(click)="sideToggle('update')"
>수정</app-button
>
- 템플릿