Ionic MenuBar

agnusdei·2023년 7월 5일
0
import { Injectable, Type } from '@angular/core';
import { Subject } from 'rxjs';

export type CreateSidebarOptions = {
  component: Type<any>;
  componentProps?: any;
};

@Injectable({
  providedIn: 'root',
})
export class SidebarService {
  // Subject is a type of observable that allows multicasting, meaning it can have multiple subscribers
  // open$ is a subject that emits a value when a sidebar needs to be opened
  open$: Subject<CreateSidebarOptions> = new Subject<CreateSidebarOptions>();

  // close$ is a subject that emits a value when a sidebar needs to be closed
  close$: Subject<void> = new Subject<void>();

  constructor() {}

  // Method to open a sidebar with the provided data
  async open(data: CreateSidebarOptions) {
    this.open$.next(data);
  }

  // Method to dismiss/close the sidebar
  dismiss() {
    this.close$.next();
  }
}
  1. 서비스를 활용하여 핸들링하겠습니다.
<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()"
    />
    <!-- virtual area instance -->
    <ng-template #container />
  </div>
</ion-menu>
  1. 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();
  }
}
  1. 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>
    <!-- side ion-menu -->
    <app-sidebar />
  </section>
</ion-content>
  1. 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();
      },
    });
  }
  1. 메뉴를 여는 컴포넌트 내부
<app-button
        (click)="sideToggle('update')"
        >수정</app-button
      >
  1. 템플릿

0개의 댓글