계층적 그리드 로드 온디맨드
Ignite UI for Angular IgxHierarchicalGrid
서버에서 최소한의 데이터만 검색하여 요청함으로써 빠른 렌더링을 허용하여 사용자가 결과를 뷰에서 보고 가능한 한 빨리 표시되는 데이터와 상호 작용할 수 있도록 합니다. 처음에는 루트 그리드의 데이터만 검색하여 렌더링하고, 사용자가 자식 그리드가 포함된 행을 확장한 후에만 해당 자식 그리드에 대한 데이터를 수신합니다. 이 메커니즘은 Load on Demand라고도 하며, 모든 원격 데이터와 작동하도록 쉽게 구성할 수 있습니다.
이 항목에서는 Northwind WebAPI에서 데이터를 요청하여 요청 시 로드를 구성하는 방법을 보여 줍니다. 다음은 작업 데모이며 나중에 단계별로 살펴보고 만드는 과정을 설명합니다.
Angular 계층형 그리드 로드 온 디맨드 예제
이 샘플이 마음에 드시나요? 전체 Ignite UI for Angular 툴킷에 액세스하고 몇 분 안에 나만의 앱을 구축해 보세요. 무료로 다운로드하세요.
계층적 그리드 설정
계층적 그리드를 설정해 보겠습니다. 먼저 우리는 우리가 가질 것으로 예상되는 계층 수준으로 hierarchical grid 템플릿을 정의할 것입니다. 우리는 고객에 대한 루트 그리드 primaryKey
가 customerId
첫 번째 수준의 orderId
주문에 대한 것이고 각각 주문 세부 정보에 productId
대한 것임을 알고 있습니다. 각 데이터베이스 테이블과 해당 키를 알면 초기 템플릿을 정의할 수 있습니다.
<igx-hierarchical-grid #hGrid [primaryKey]="'customerId'" [autoGenerate]="true" [height]="'600px'" [width]="'100%'">
<igx-row-island [key]="'Orders'" [primaryKey]="'orderId'" [autoGenerate]="true">
<igx-row-island [key]="'Details'" [primaryKey]="'productId'" [autoGenerate]="true">
</igx-row-island>
</igx-row-island>
</igx-hierarchical-grid>
html
참조를 사용할 #hGrid
수 있으므로 나중에 코드의 엔드포인트에서 데이터를 가져온 후 루트 그리드의 데이터를 쉽게 설정할 것입니다. 확장된 자식에 대한 데이터를 설정하는 것은 약간 다릅니다.
행이 처음으로 확장되면 새 자식 IgxHierarchicalGrid
이 렌더링되고 데이터를 설정하려면 새로 생성된 그리드에 대한 참조를 가져와야 합니다. 그렇기 때문에 각 IgxRowIsland
구성 요소는 해당 특정 행 아일랜드에 대해 새 자식 그리드가 생성될 때 발생하는 이벤트를 제공합니다 gridCreated
. 이를 사용하여 새 그리드에 필요한 참조를 가져오고, 엔드포인트에서 데이터를 요청하고, 적용할 수 있습니다.
엔드포인트에는 행 아일랜드의 키, 부모 행의 기본 키 및 고유 식별자만 필요하기 때문에 모든 행 아일랜드에 대해 하나의 방법을 사용할 수 있습니다. 이 모든 정보는 이벤트 인수에서 직접 액세스할 수 있습니다.
로딩 표시 설정
이제 사용자에게 데이터가 아직 로드 중임을 알려 그 동안 빈 그리드를 볼 필요가 없도록 하여 사용자 경험을 개선해 보겠습니다. 그렇기 때문에 그리드가 IgxHierarchicalGrid
비어 있는 동안 표시할 수 있는 로딩 표시기를 지원합니다.
데이터를 없는 동안으로 isLoading
속성을 true
설정하여 로딩 표시기를 표시합니다. 처음에는 루트 그리드에 대해 설정해야 하며 데이터가 로드될 때까지 새 자식 그리드를 만들 때도 설정해야 합니다. 템플릿에서 항상 설정할 true
수 있지만 설정하여 숨기 false
고 서비스가 빈 배열을 반환하는 경우 그리드에 데이터가 없음을 표시하려고 합니다.
마지막으로, 속성을 끄고 autoGenerate
태그에서 columns 컬렉션을 정의해 보겠습니다.
모든 변경 사항이 추가된 후 템플릿 파일은 hierarchical-grid-lod.component.html
다음과 같습니다.
<igx-hierarchical-grid #hGrid [data]="remoteData" [isLoading]="true" [primaryKey]="'customerId'" [autoGenerate]="false" [height]="'580px'" [width]="'100%'" [igxPreventDocumentScroll]="true" [allowAdvancedFiltering]="true" [schema]="schema" (advancedFilteringExpressionsTreeChange)="refreshRootGridData()">
<igx-grid-toolbar></igx-grid-toolbar>
<igx-column field="customerId" [dataType]="'string'"></igx-column>
<igx-column field="companyName" [dataType]="'string'"></igx-column>
<igx-column field="contactName" [dataType]="'string'"></igx-column>
<igx-column field="contactTitle" [dataType]="'string'"></igx-column>
<igx-row-island #rowIsland1 [key]="'Orders'" [primaryKey]="'orderId'" [autoGenerate]="false" (gridCreated)="gridCreated($event)">
<igx-column field="orderId"></igx-column>
<igx-column field="customerId"></igx-column>
<igx-column field="shipVia"></igx-column>
<igx-column field="freight"></igx-column>
<igx-row-island #rowIsland2 [key]="'Details'" [primaryKey]="'orderId'" [autoGenerate]="false" (gridCreated)="gridCreated($event)">
<igx-column field="orderId"></igx-column>
<igx-column field="productId"></igx-column>
<igx-column field="unitPrice"></igx-column>
<igx-column field="quantity"></igx-column>
<igx-column field="discount"></igx-column>
</igx-row-island>
</igx-row-island>
</igx-hierarchical-grid>
html
고급 필터링
with load on demand에서 Advanced Filtering을 IgxHierarchicalGrid
사용하려면 그리드의 속성을 계층 구조를 가진 엔터티로 설정하고 schema
자식 엔터티와 필드를 데이터 유형으로 지정해야 합니다. 이렇게 하면 자식 그리드 데이터가 로드되기 전에도 중첩된 쿼리가 있는 필터링 표현식을 만들 수 있으며 그리드가 이러한 필터를 올바르게 해석하고 데이터에 적용할 수 있습니다.
우리의 경우 올바른 계층 구조는 다음과 같습니다.
public schema: EntityType[] = [
{
name: 'Customers',
fields: [
{ field: 'customerId', dataType: 'string' },
{ field: 'companyName', dataType: 'string' },
{ field: 'contactName', dataType: 'string' },
{ field: 'contactTitle', dataType: 'string' }
],
childEntities: [
{
name: 'Orders',
fields: [
{ field: 'customerId', dataType: 'string' },
{ field: 'orderId', dataType: 'number' },
{ field: 'employeeId', dataType: 'number' },
{ field: 'shipVia', dataType: 'string' },
{ field: 'freight', dataType: 'number' }
],
childEntities: [
{
name: 'Details',
fields: [
{ field: 'orderId', dataType: 'number' },
{ field: 'productId', dataType: 'number' },
{ field: 'unitPrice', dataType: 'number' },
{ field: 'quantity', dataType: 'number' },
{ field: 'discount', dataType: 'number' }
]
}
]
}
]
}
];
TypeScript
초기 필터 설정
이제 루트 그리드가 처음 로드될 때 필터링되도록 그리드에 초기 필터링 규칙을 추가해 보겠습니다. 우리는 만들 것입니다 FilteringExpressionsTree
을 클릭하고 advancedFilteringExpressionsTree
의 속성 IgxHierarchicalGrid
를 사용하여 ngOnInit
라이프사이클 훅.
최소한 500
주문한 화물이 있는 고객을 필터링하고 싶다고 가정해 보겠습니다. 필터링 표현식에서 중첩된 쿼리를 만드는 기능을 활용하면 다음과 같은 결과가 나타납니다.
public ngOnInit() {
const ordersTree = new FilteringExpressionsTree(FilteringLogic.And, undefined, 'Orders', ['customerId']);
ordersTree.filteringOperands.push({
fieldName: 'freight',
ignoreCase: false,
condition: IgxNumberFilteringOperand.instance().condition('greaterThanOrEqualTo'),
conditionName: IgxNumberFilteringOperand.instance().condition('greaterThanOrEqualTo').name,
searchVal: '500'
});
const customersTree = new FilteringExpressionsTree(FilteringLogic.And, undefined, 'Customers', ['customerId', 'companyName', 'contactName', 'contactTitle']);
customersTree.filteringOperands.push({
fieldName: 'customerId',
condition: IgxStringFilteringOperand.instance().condition('inQuery'),
conditionName: IgxStringFilteringOperand.instance().condition('inQuery').name,
ignoreCase: false,
searchTree: ordersTree
});
this.hGrid.advancedFilteringExpressionsTree = customersTree;
}
TypeScript
엔드포인트에 연결
브라우저가 제공하는 XMLHttpRequest 인터페이스를 사용하여 HTTP 프로토콜을 통해 엔드 포인트와 통신 할 것입니다. 이를 보다 쉽게 달성하기 위해 단순화된 클라이언트 HTTP API를 제공하는 Angular HttpClient
의 모듈을 사용합니다.
루트 그리드 데이터 가져오기
Northwind WebAPI는 매개 변수로 허용하는 IFilteringExpressionsTree
POST 엔드포인트를 제공하며, 루트 그리드에서 IgxHierarchicalGrid
고급 필터링 기능을 활용하고 레코드를 필터링하기 위해 이 엔드포인트를 사용합니다. 우리는 이것을 refreshRootGridData
방법으로 할 것입니다 :
public refreshRootGridData() {
const tree = this.hGrid.advancedFilteringExpressionsTree;
this.hGrid.isLoading = true;
if (tree) {
this.http.post(`${API_ENDPOINT}/QueryBuilder/ExecuteQuery`, tree).subscribe(data =>{
this.remoteData = Object.values(data)[0];
this.hGrid.isLoading = false;
this.hGrid.cdr.detectChanges();
});
} else {
this.http.get(`${API_ENDPOINT}/Customers`).subscribe(data => {
this.remoteData = Object.values(data);
this.hGrid.isLoading = false;
this.hGrid.cdr.detectChanges();
});
}
}
typescript
보시다시 this.http
피 모듈에 대한 HttpCLient
참조가 있습니다. 이 subscribe
메소드는 Angular의 Observable의 일부이며 HTTP 요청의 비동기 응답을 처리하는 데 사용됩니다. 데이터가 수신되면 가져온 데이터를 관련 그리드에 할당하고, 로드 상태를 false로 업데이트하고, 변경 감지를 트리거하여 UI에 변경 내용이 반영되도록 합니다.
루트 그리드가 처음 렌더링된 후 데이터를 로드하기 위해 lifecycle 후크를 ngAfterViewInit
사용하고 메서드를 호출합니다. refreshRootGridData
public ngAfterViewInit() {
this.refreshRootGridData();
}
TypeScript
자식 그리드 데이터 가져오기
다음으로 하위 그리드에 대한 데이터를 가져오기 위해 GET 요청에 대한 URL을 빌드하는 방법을 정의합니다. 다음은 테이블 간의 관계를 시각적으로 표현한 것입니다.

마지막으로, 생성된 모든 새 자식 그리드에 대한 데이터를 요청하는 메서드를 구현 gridCreated
해야 합니다. 루트 수준 그리드 데이터를 가져오는 것과 유사하며, 이번에는 이벤트에 gridCreated
제공된 데이터를 사용하고 이를 사용하여 URL을 빌드합니다.
public gridCreated(event: IGridCreatedEventArgs) {
event.grid.isLoading = true;
const url = this.buildUrl(event);
this.http.get(url).subscribe(data => {
event.grid.data = Object.values(data);
event.grid.isLoading = false;
this.hGrid.cdr.detectChanges();
});
}
private buildUrl(event: IGridCreatedEventArgs) {
const parentKey = (event.grid.parent as any).key ?? this.schema[0].name;
const url = `${API_ENDPOINT}/${parentKey}/${event.parentID}/${event.owner.key}`;
return url;
}
TypeScript