깜놀하는 해므찌로

Apexchart toggle custom 아펙스차트 토글 커스텀 예시 본문

IT

Apexchart toggle custom 아펙스차트 토글 커스텀 예시

agnusdei1207 2023. 8. 19. 18:53
반응형
SMALL
<apx-chart
  class="block w-full h-full"
  [series]="chartOptions.series!"
  [chart]="chartOptions.chart!"
  [xaxis]="chartOptions.xaxis!"
  [dataLabels]="chartOptions.dataLabels!"
  [stroke]="chartOptions.stroke!"
  [yaxis]="chartOptions.yaxis!"
  [responsive]="chartOptions.responsive!"
  [legend]="chartOptions.legend"
  *ngIf="!isLoading"
>
</apx-chart>

1. chart 컴포넌트 템플릿

import {
  Component,
  HostBinding,
  Input,
  OnInit,
  ViewChild,
} from '@angular/core';
import { CommonModule } from '@angular/common';
import {
  ApexAxisChartSeries,
  ApexChart,
  ApexDataLabels,
  ApexLegend,
  ApexResponsive,
  ApexStroke,
  ApexTitleSubtitle,
  ApexXAxis,
  ApexYAxis,
  NgApexchartsModule,
  ChartComponent as ApexChartComponent, // as 를 활용해서 자신 컴포넌트 이름 변경
} from 'ng-apexcharts';

export type ChartOptions = {
  series: ApexAxisChartSeries;
  chart: ApexChart;
  xaxis: ApexXAxis;
  stroke: ApexStroke;
  dataLabels: ApexDataLabels;
  yaxis: ApexYAxis;
  labels: string[];
  legend: ApexLegend;
  subtitle: ApexTitleSubtitle;
  responsive: ApexResponsive[];
};

@Component({
  selector: 'app-chart',
  standalone: true,
  imports: [CommonModule, NgApexchartsModule],
  templateUrl: './chart.component.html',
  styleUrls: ['./chart.component.scss'],
})
export class ChartComponent implements OnInit {
  
  // 이름을 변경한 컴포넌트를 viewChild 데코 타입으로 선언하기
  @ViewChild(ApexChartComponent) chartComponent!: ApexChartComponent;
  
  
  @Input() chartOptions!: ChartOptions;
  @Input() categories: ApexXAxis['categories'] = [
    '1월',
    '2월',
    '3월',
    '4월',
    '5월',
    '6월',
    '7월',
    '8월',
    '9월',
    '10월',
    '11월',
    '12월',
  ];
  @Input({ required: true }) series!: ApexAxisChartSeries;
  isLoading: boolean = true;

  @HostBinding('class') class = 'block w-full h-full';

  constructor() {}

  ngOnInit() {
    if (!this.chartOptions) {
      this.chartOptions = {
        series: this.series,
        responsive: [{ breakpoint: undefined, options: {} }],
        chart: {
          type: 'line',
          fontFamily: 'Pretendard',
          width: '100%',
          height: '100%',
          toolbar: {
            show: false,
          },
          zoom: {
            enabled: false,
          },
        },
        dataLabels: {
          enabled: false,
        },
        stroke: {
          curve: 'straight',
          width: 2,
        },
        subtitle: {
          text: 'Price Movements',
          align: 'left',
        },
        labels: ['labels'],
        xaxis: {
          categories: this.categories,
        },
        yaxis: {
          opposite: false,
        },
        legend: {
          show: false,
        },
      };
    }
  }

  async ngAfterViewInit() {
    setTimeout(() => {
      this.isLoading = false;
    }, 1000);
  }
}

2. 차트 컴포넌트 내부 (주석 참조)

3. 차트 컴포넌트를 호출하는 부모 컴포넌트에서 핸들링 하기 위해, 자기 자신을 ViewChild 데코 타입으로 바꾸는 것입니다.

 

<!-- 차트 컴포넌트 -->
<app-chart #salesChart [series]="salesSeries"></app-chart>

4. 부모 컴포넌트에서 차트 컴포넌트를 호출합니다.

5. 차트 컴포넌트를 saleChart 라는 이름으로 viewChild 를 걸어 줍니다.

 

 

// 차트 컴포넌트 타입으로 viewchild 변수 선언
@ViewChild('salesChart') salesChartComponent!: ChartComponent; 


// 예시 용도 시리즈 데이터
  salesSeries: ApexAxisChartSeries = [
    {
      name: '2023',
      data: [
        1000, 1100, 1200, 1300, 1200, 1100, 1000, 1200, 1300, 1400, 1300, 1350,
      ],
      color: '#22C55E',
    },
    {
      name: '2022',
      data: [10, 50, 100, 110, 120, 120, 130, 140, 150, 165, 170, 350],
      color: '#a855f7',
    },
    {
      name: '2021',
      data: [1000, 900, 700, 650, 600, 650, 700, 705, 700, 600, 750, 900],
      color: '#eab308',
    },
    {
      name: '2020',
      data: [
        1500, 1300, 1200, 1100, 1000, 900, 1000, 1100, 1200, 1300, 1400, 1500,
      ],
      color: '#3b82f6',
    },
  ];

// 클릭 시 토글 핸들링 메소드
  handleSalesChartSegments(toBeShown?: string) {
  
    const seriesNames = this.salesSeries.map((series) => series.name!);
    // 전체가 아닌 경우
    if (toBeShown) {
      for (const name of seriesNames.filter((_name) => _name !== toBeShown)) {
      // 자식 컴포넌트에 접근하여 apex 내장 함수를 활용해 원하는 범위만 가리기
        this.salesChartComponent.chartComponent.hideSeries(name);
      }
	// 특정 범위만 보여주기
      this.salesChartComponent.chartComponent.showSeries(toBeShown);
      
      // 전체 클릭 시
    } else {
      for (const name of seriesNames) {
      // 전부 보여주기
        this.salesChartComponent.chartComponent.showSeries(name);
      }
    }
  }

6. 설명이 길어, 상세내용은 주석을 참고해 주세요.

 

 

<div class="flex items-center justify-between">
        <lepi-segment>
        <!-- 클릭 함수 호출 -->
          <lepi-segment-item (click)="handleSalesChartSegments()"
            >모두</lepi-segment-item
          >
          <!-- 클릭 함수 호출 -->
          <lepi-segment-item
            *ngFor="let series of salesSeries"
            (click)="handleSalesChartSegments(series.name)"
          >
            <div class="flex items-center gap-1">
              <div
                class="w-3 h-3 rounded-full"
                [ngStyle]="{'background-color': series.color}"
              ></div>
              <div>{{series.name}}</div>
            </div>
          </lepi-segment-item>
        </lepi-segment>
        <app-select
          formControlName="type"
          [search]="false"
          placeholder="연간 매출"
        >
          <app-option-group>
            <app-option>2023</app-option>
            <app-option>2022</app-option>
            <app-option>2021</app-option>
            <app-option>2020</app-option>
          </app-option-group>
        </app-select>
      </div>
      <!-- 차트 컴포넌트 -->
      <app-chart #salesChart [series]="salesSeries"></app-chart>
    </div>

 

반응형
LIST