Angular Grid Selection-Based Data Aggregation
뒤에 설명된 샘플을 통해 사용자 정의 요약 기능과 함께 다중 선택이 사용되어 그리드 바닥글에서 선택한 값을 기반으로 집계를 표시하는 방법을 확인할 수 있습니다.
주제 개요
선택 기반 집계 기능을 구현하려면 Grid Summaries
과 함께 Grid Selection
기능을 사용할 수 있습니다. 요약을 사용하면 열 데이터 유형 및 요구 사항에 따라 기본 클래스 IgxSummaryOperand
, IgxNumberSummaryOperand
또는 IgxDateSummaryOperand
중 하나를 확장하여 기본 요약 기능을 사용자 정의할 수 있습니다.
선택
선택한 그리드 범위의 데이터 작업을 시작하려면 그리드 선택의 변경 사항을 알리는 이벤트를 구독해야 합니다. 이는 selected
이벤트와 rangeSelected
이벤트를 구독하여 수행할 수 있습니다. 선택 기능은 단일 셀 선택과 셀 범위 선택을 구별하므로 두 가지 모두에 바인딩해야 합니다.
이벤트 구독 로직에서 그리드의 getSelectedData
함수를 사용하여 선택한 데이터를 추출하고 선택한 데이터를 사용자 정의 요약 피연산자에 전달할 수 있습니다.
요약
사용자 정의 요약 클래스 내에서는 그리드의 데이터 유형을 구별해야 합니다. 예를 들어 아래 시나리오에는 사용자 정의 요약에 적합한 데이터 유형의 네 가지 열이 있습니다. 이는 단가, 재고 수량, 단종 상태 및 주문 날짜입니다. IgxSummaryOperand
의 파생 클래스의 operate
메소드는 데이터 유형에 따라 다양한 카테고리로 분류하여 데이터를 처리하는 곳입니다.
const numberData = data.filter(rec => typeof rec === "number" );
const boolData = data.filter(rec => typeof rec === "boolean" );
const dates = data.filter(rec => isDate(rec));
typescript
Bear in mind, that isDate
is a custom function.
데이터 유형을 적절하게 그룹화한 후 집계 자체를 진행할 수 있습니다. 이러한 이유로 IgxNumberSummaryOperand
및 IgxDateSummaryOperand
의 이미 노출된 메서드를 사용할 수 있습니다. 그런 다음 집계된 데이터를 동일한 배열에 넣어야 하며 이는 템플릿에 반환됩니다. 데이터 시각화를 위해 <igx-grid-footer>
를 사용할 수 있습니다. 이는 custom-summaries
클래스와 함께 요약의 자연스러운 모양을 제공합니다.
데모
현재 선택한 범위의 요약을 보려면 선택 항목을 변경하세요.
import { formatDate, NgIf, NgFor } from '@angular/common' ;
import { AfterViewInit, Component, ViewChild, OnInit, ChangeDetectorRef} from '@angular/core' ;
import { IgxDateSummaryOperand, IgxGridComponent, IgxNumberSummaryOperand, IgxSummaryOperand, IgxSummaryResult, IgxColumnComponent, IgxCellTemplateDirective, IgxGridFooterComponent } from 'igniteui-angular' ;
import { DATA } from '../../data/nwindData' ;
import { IgxPreventDocumentScrollDirective } from '../../directives/prevent-scroll.directive' ;
class MySummary {
public operate(data: any [] = []): IgxSummaryResult[] {
const result = new IgxSummaryOperand().operate(data);
if (data.length < 1 ) { return result; }
const numberData = data.filter(rec => typeof rec === 'number' );
const boolData = data.filter(rec => typeof rec === 'boolean' );
const dates = data.filter(rec => isDate(rec));
if (numberData.length) {
result.push({ key : 'min' , label : 'Min' , summaryResult : IgxNumberSummaryOperand.min(numberData)});
result.push({ key : 'max' , label : 'Max' , summaryResult : IgxNumberSummaryOperand.max(numberData)});
result.push({ key : 'avg' , label : 'Avg' , summaryResult : IgxNumberSummaryOperand.average(numberData)});
result.push({ key : 'sum' , label : 'Sum' , summaryResult : IgxNumberSummaryOperand.sum(numberData)});
}
if (boolData.length) {
result.push({
key : 'test' , label : 'Discounted' ,
summaryResult : boolData.filter(rec => rec).length + ' of ' + boolData.length });
}
if (dates.length) {
result.push({ key : 'earliest' , label : 'Earliest' , summaryResult : IgxDateSummaryOperand.earliest(dates)});
result.push({ key : 'latest' , label : 'Latest' , summaryResult : IgxDateSummaryOperand.latest(dates)});
}
return result;
}
}
@Component ({
selector : 'app-grid-sample' ,
styleUrls : ['./grid-custom-summaries-selection.component.scss' ],
templateUrl : 'grid-custom-summaries-selection.component.html' ,
imports : [IgxGridComponent, IgxPreventDocumentScrollDirective, IgxColumnComponent, IgxCellTemplateDirective, NgIf, IgxGridFooterComponent, NgFor]
})
export class GridCustomSummariesSelectionComponent implements AfterViewInit , OnInit {
@ViewChild ('grid1' , { static : true }) public grid1: IgxGridComponent;
public data: any [];
public selectionSummaries = [];
private customSummary = new MySummary();
constructor (private cdr: ChangeDetectorRef ) { }
public ngOnInit(): void {
this .data = DATA;
}
public ngAfterViewInit(): void {
this .grid1.setSelection({
rowStart : 2 , rowEnd : 4 ,
columnStart : 1 , columnEnd : 4
});
this .calculateSummary();
this .cdr.detectChanges();
}
public format (value: any ) {
if (typeof value === 'number' ) {
return value.toFixed(2 );
} else if (isDate(value)) {
return formatDate(value, 'mediumDate' , 'en' );
}
return value;
}
public formatCurrency (value: number ) {
if (!value) { return ; }
return '$' + value.toFixed(2 );
}
public calculateSummary ( ) {
this .selectionSummaries = this .customSummary.operate(this .toArray(this .grid1.getSelectedData()));
}
public toArray (data ) {
let result = [];
data.forEach(rec => result = result.concat(Object .values(rec)));
return result;
}
}
function isDate (value: any ) {
return Object .prototype.toString.call(value) === '[object Date]' ;
}
ts コピー <div class ="grid__wrapper" >
<igx-grid [igxPreventDocumentScroll ]="true" #grid1 [data ]="data" [height ]="'530px'" [width ]="'100%'"
(selected )='calculateSummary()'
(rangeSelected )='calculateSummary()' >
<igx-column [field ]="'ProductID'" > </igx-column >
<igx-column [field ]="'ProductName'" > </igx-column >
<igx-column [field ]="'UnitPrice'" [dataType ]="'number'" [formatter ]="formatCurrency" > </igx-column >
<igx-column [field ]="'UnitsInStock'" [dataType ]="'number'" > </igx-column >
<igx-column [field ]="'Discontinued'" [dataType ]="'boolean'" >
<ng-template igxCell let-cell ="cell" let-val >
<img *ngIf ="val" src ="https://www.infragistics.com/angular-demos-lob/assets/images/grid/active.png" title ="Continued" alt ="Continued" />
<img *ngIf ="!val" src ="https://www.infragistics.com/angular-demos-lob/assets/images/grid/expired.png" title ="Discontinued" alt ="Discontinued" />
</ng-template >
</igx-column >
<igx-column [field ]="'OrderDate'" [dataType ]="'date'" > </igx-column >
<igx-grid-footer >
<div class ="custom-summaries" >
<div *ngFor ="let summary of selectionSummaries" class ="summaries-data-wrapper" >
<span class ="igx-grid-summary__label" > {{ summary.label }}</span >
<span class ="igx-grid-summary__result" > {{ format(summary.summaryResult) }}</span >
</div >
</div >
</igx-grid-footer >
</igx-grid >
</div >
html コピー .cellAlignSyle {
text-align : right;
float :right ;
}
.cellAlignSyle > span {
float :right ;
}
.up {
color : green;
}
.down {
color : red;
}
.headerAlignSyle {
text-align : right !important ;
}
.sample-container {
width : 20% ;
display : flex;
margin : 0% 0% 20px 10px
}
.grid-controls {
display: flex;
justify-content : space-between;
margin : 0 16px 24px ;
flex-flow : column;
align-items : flex-start;
}
.grid__wrapper {
margin : 0 16px ;
padding-top : 16px ;;
}
.currency-badge-container {
width : 80px ;
float : right;
}
.badge-left {
float : left;
}
div .igx-grid__tfoot {
z-index : 1 ;
}
.custom-summaries {
margin-left : auto;
width : 100% ;
display : flex;
flex-direction : row;
justify-content : flex-end;
}
.summaries-data-wrapper { display : inline-block; padding-right : 24px ; }
.summaries-data-wrapper span :first -child { margin-right : 16px }
scss コピー
이 샘플이 마음에 드시나요? 전체 Ignite UI for Angular 툴킷에 액세스하고 몇 분 안에 나만의 앱을 구축해 보세요. 무료로 다운로드하세요.
API 참조
추가 리소스
우리 커뮤니티는 활동적이며 항상 새로운 아이디어를 환영합니다.