계층적 그리드 로드 온디맨드

    이 Ignite UI for Web Components IgcHierarchicalGridComponent는 사용자가 가능한 한 빨리 결과를 보고 표시되는 데이터와 상호 작용할 수 있도록 서버에서 검색할 최소한의 데이터를 요청하여 빠른 렌더링을 가능하게 합니다. 처음에는 루트 그리드의 데이터만 검색되고 렌더링되며, 사용자가 자식 그리드가 포함된 행을 확장한 후에만 해당 특정 자식 그리드에 대한 데이터를 받게 됩니다. Load on Demand라고도 하는 이 메커니즘은 모든 원격 데이터와 함께 작동하도록 쉽게 구성할 수 있습니다.

    이 항목에서는 이미 사용 가능한 원격 서비스와 통신하는 원격 서비스 공급자를 만들어 요청 시 로드를 구성하는 방법을 보여 줍니다. 다음은 작업 데모이며 나중에 단계별로 살펴보고 생성 과정을 설명합니다.

    Web Components Hierarchical Grid Load On Demand Example

    Remote Service Provider

    먼저 계층적 그리드에 필요한 데이터를 얻을 수 있도록 서비스 공급자를 준비합니다.

    기본 데이터 가져오기

    브라우저가 제공하는 전역 기능을 사용하여 fetch() HTTP 프로토콜을 통해 백엔드 서비스와 통신할 것입니다. 그렇게하면 데이터를 얻으려면 서비스에서 다음과 같은 간단한 방법이 필요합니다.

    export function getData(dataState: any): any {
        return fetch(buildUrl(dataState))
            .then((result) => result.json());
    }
    

    보시다시피 buildUrl() 우리가받은 데이터를 기반으로 URL을 생성하는 방법이 될 것입니다. Promise는 비동기적으로 실행되기 때문에 반환합니다. 그렇게하면 나중에 구독하고 응용 프로그램에서 추가로 처리하여 그리드에 전달할 수 있습니다.

    요청 URL 작성

    다음으로 GET 요청에 대한 URL을 작성하는 방법을 정의합니다. 여기에서 기본 그리드에 대한 데이터뿐만 아니라 그 안의 모든 자식 그리드에 대한 데이터도 얻을 수 있습니다. 우리는 사용할 것입니다 Customers 데이터 출처 여기 루트 수준과 사용을 위해 Orders 그리고 Details 낮은 수준의 경우. 모델은 응용 프로그램마다 다르지만 다음 모델을 사용합니다.

    가장 먼저 필요한 것은 원하는 그리드에 대한 데이터를 가져올 위치, 상위 행의 기본 키 및 고유 ID를 결정하는 테이블입니다 key.

    우리는 이 모든 것을 객체에서 dataState 정의할 것입니다. 예를 들면 다음과 같습니다.

    const dataState: {
        key: string;
        parentID: any;
        parentKey: string;
        rootLevel: boolean;
    } = {
        //...
    };
    
    function buildUrl(dataState: any) {
        let qS = "";
        if (dataState) {
            if (dataState.rootLevel) {
                qS += `${dataState.key}`;
            } else {
                qS += `${dataState.parentKey}/${dataState.parentID}/${dataState.key}`;
            }
        }
        return `${URL}${qS}`;
    }
    

    결과

    마지막으로 원격 서비스는 다음과 같습니다.

    const URL = `https://data-northwind.indigo.design/`;
    
    export function getData(dataState: any): any {
        return fetch(buildUrl(dataState))
            .then((result) => result.json());
    }
    
    function buildUrl(dataState: any) {
        let qS = "";
        if (dataState) {
            if (dataState.rootLevel) {
                qS += `${dataState.key}`;
            } else {
                qS += `${dataState.parentKey}/${dataState.parentID}/${dataState.key}`;
            }
        }
        return `${URL}${qS}`;
    }
    

    Hierarchical Grid Setup

    다음으로 계층적 그리드를 설정하고 이를 원격 서비스 공급자에 연결하겠습니다.

    템플릿 정의

    먼저 우리는 우리가 기대하는 계층 수준으로 계층적 그리드 템플릿을 정의할 것입니다. 우리는 고객에 대한 루트 그리드 PrimaryKeycustomerId 첫 번째 수준의 orderId 주문과 주문 세부 정보에 대한 주문이라는 것을 알고 있습니다 productId. 각 데이터베이스 테이블과 해당 키를 알면 초기 템플릿을 정의할 수 있습니다.

    <igc-hierarchical-grid id="hGrid" primary-key="customerId" height="600px">
        <igc-column field="customerId" hidden="true"></igc-column>
        <igc-column field="companyName" header="Company Name"></igc-column>
        <igc-column field="contactName" header="Contact Name"></igc-column>
        <igc-column field="contactTitle" header="Contact Title"></igc-column>
        <igc-column field="address.country" header="Country"></igc-column>
        <igc-column field="address.phone" header="Phone"></igc-column>
        <igc-row-island child-data-key="Orders" primary-key="orderId">
            <igc-column field="orderId" hidden="true"></igc-column>
            <igc-column field="shipAddress.country" header="Ship Country"></igc-column>
            <igc-column field="shipAddress.city" header="Ship City"></igc-column>
            <igc-column field="shipAddress.street" header="Ship Address"></igc-column>
            <igc-column field="orderDate" header="Order Date" data-type="date"></igc-column>
            <igc-row-island child-data-key="Details" primary-key="productId">
                <igc-column field="productId" hidden="true"></igc-column>
                <igc-column field="quantity" header="Quantity"></igc-column>
                <igc-column field="unitPrice" header="Unit Price"></igc-column>
                <igc-column field="discount" header="Discount"></igc-column>
            </igc-row-island>
        </igc-row-island>
    </igc-hierarchical-grid>
    

    하지만 템플릿에는 한 가지 빠진 것이 있는데, 그것은 루트 수준 계층적 그리드에 대한 데이터이며, 결국 그 자식입니다.

    참조를 사용할 id="hGrid" 수 있으므로 나중에 코드의 서비스에서 데이터를 가져온 후 루트 그리드의 데이터를 쉽게 설정할 것입니다.

    확장된 자식에 대한 데이터를 설정하는 것은 약간 다릅니다. 행이 처음으로 확장되면 새 자식 IgcHierarchicalGridComponent이 렌더링되고 새로 생성된 그리드에 대한 참조를 가져와 데이터를 설정해야 합니다. 따라서 각 IgcRowIsland 구성 요소는 해당 특정 행 아일랜드에 대해 새 자식 그리드가 생성될 때 발생하는 이벤트를 제공합니다 GridCreated. 이를 사용하여 새 그리드에 필요한 참조를 가져오고, 서비스에서 해당 데이터를 요청하고, 적용할 수 있습니다.

    루트 수준, 행 아일랜드의 키, 상위 행의 기본 키 및 고유 식별자인 경우에만 정보가 필요하도록 서비스를 구축했기 때문에 모든 행 아일랜드에 대해 하나의 방법을 사용할 수 있습니다. 이 모든 정보는 이벤트 인수에서 직접 액세스하거나 이벤트 트리거를 담당하는 행 아일랜드에서 액세스할 수 있습니다.

    사용할 gridCreated 메서드의 이름을 지정해 보겠습니다.

    이벤트는 GridCreated 속성, 행 섬에 대한 참조 as owner 및 새 자식 grid 속성을 제공하기 parentID 때문에 첫 번째 인수로 전달됩니다. 부모 행 primaryKey에 대한 정보만 누락되었지만 바인딩하는 행 아일랜드에 따라 두 번째 인수로 쉽게 전달할 수 있습니다.

    이러한 변경 내용이 추가된 템플릿 파일은 다음과 같습니다.

    <igc-hierarchical-grid id="hGrid" primary-key="customerId" height="600px">
        <igc-column field="customerId" hidden="true"></igc-column>
        <igc-column field="companyName" header="Company Name"></igc-column>
        <igc-column field="contactName" header="Contact Name"></igc-column>
        <igc-column field="contactTitle" header="Contact Title"></igc-column>
        <igc-column field="address.country" header="Country"></igc-column>
        <igc-column field="address.phone" header="Phone"></igc-column>
        <igc-row-island id="ordersRowIsland" child-data-key="Orders" primary-key="orderId">
            <igc-column field="orderId" hidden="true"></igc-column>
            <igc-column field="shipAddress.country" header="Ship Country"></igc-column>
            <igc-column field="shipAddress.city" header="Ship City"></igc-column>
            <igc-column field="shipAddress.street" header="Ship Address"></igc-column>
            <igc-column field="orderDate" header="Order Date" data-type="date"></igc-column>
            <igc-row-island id="orderDetailsRowIsland" child-data-key="Details" primary-key="productId">
                <igc-column field="productId" hidden="true"></igc-column>
                <igc-column field="quantity" header="Quantity"></igc-column>
                <igc-column field="unitPrice" header="Unit Price"></igc-column>
                <igc-column field="discount" header="Discount"></igc-column>
            </igc-row-island>
        </igc-row-island>
    </igc-hierarchical-grid>
    
    constructor() {
        const ordersRowIsland = document.getElementById("ordersRowIsland");
        const orderDetailsRowIsland = document.getElementById("orderDetailsRowIsland");
    
        ordersRowIsland.addEventListener("gridCreated", (event: any) => {
            this.gridCreated(event, "Customers");
        });
    
        orderDetailsRowIsland.addEventListener("gridCreated", (event: any) => {
            this.gridCreated(event, "Orders");
        });
    }
    

    우리 서비스 연결하기

    이제 마지막 단계 중 하나는 이전에 만든 서비스를 계층적 그리드에 연결하는 것입니다.

    데이터를 설정하기 위해 루트 그리드에 대한 참조를 얻을 것입니다. 부모가 없기 때문에 우리는 그것이 rootLevel​ ​사실 이고 그것의 getData 열쇠를 우리의 서비스에 전달할 수 있습니다. Promise를 반환하므로 구독해야 합니다.

    constructor() {
        const hierarchicalGrid = document.getElementById("hGrid") as IgcHierarchicalGridComponent;
    
        getData({ parentID: null, rootLevel: true, key: "Customers" }).then((data: any) => {
            hierarchicalGrid.data = data;
            hierarchicalGrid.markForCheck();
        });
    }
    

    다음으로, 생성된 새 자식 그리드에 대한 데이터를 요청하는 메서드만 만들 gridCreated 면 됩니다.

    루트 수준 그리드 데이터를 가져오는 것과 비슷하며, 이번에는 and parentKey와 같은 parentID 더 많은 정보를 전달해야 합니다. rootLevel 모든 자식에 대해 false가 됩니다.

    public gridCreated(event: CustomEvent<IgcGridCreatedEventArgs>, _parentKey: string) {
        const context = event.detail;
        const dataState = {
            key: context.owner.childDataKey,
            parentID: context.parentID,
            parentKey: _parentKey,
            rootLevel: false
        };
    
        getData(dataState).then((data: any[]) => {
            context.grid.data = data;
            context.grid.markForCheck();
        });
    }
    

    이것으로 응용 프로그램 설정이 거의 완료되었습니다. 이 마지막 단계는 사용자에게 데이터가 계속 로드 중임을 알려 사용자 경험을 개선하는 것을 목표로 하므로 그 동안 빈 그리드를 볼 필요가 없습니다. 그렇기 때문에 그리드가 IgcHierarchicalGridComponent 비어 있는 동안 표시할 수 있는 로딩 표시기를 지원합니다. 새 데이터가 수신되면 로딩 표시기가 숨겨지고 데이터가 렌더링됩니다.

    로딩 표시 설정

    IgcHierarchicalGridComponent를 설정하여 로딩 표시기를 표시할 수 있습니다. IsLoading 속성을 데이터가 없는 동안. 처음에는 루트 그리드에 대해 설정해야 하며 새 자식 그리드를 만들 때도 데이터가 로드될 때까지 설정해야 합니다. 우리는 항상 그것을 설정할 수 있습니다. 템플릿에 있지만 서비스를 설정하여 서비스가 빈 배열을 반환하는 경우 그리드에 데이터가 없다는 것을 숨기고 표시하려고 합니다. 거짓.

    이 경우 구성의 최종 버전은 다음과 같습니다.

    constructor() {
        const hierarchicalGrid = document.getElementById("hGrid") as IgcHierarchicalGridComponent;
        const ordersRowIsland = document.getElementById("ordersRowIsland");
        const orderDetailsRowIsland = document.getElementById("orderDetailsRowIsland");
    
        ordersRowIsland.addEventListener("gridCreated", (event: any) => {
            this.gridCreated(event, "Customers");
        });
    
        orderDetailsRowIsland.addEventListener("gridCreated", (event: any) => {
            this.gridCreated(event, "Orders");
        });
    
        hierarchicalGrid.isLoading = true;
    
        getData({ parentID: null, rootLevel: true, key: "Customers" }).then((data: any) => {
            hierarchicalGrid.isLoading = false;
            hierarchicalGrid.data = data;
            hierarchicalGrid.markForCheck();
        });
    }
    
    public gridCreated(event: CustomEvent<IgcGridCreatedEventArgs>, _parentKey: string) {
        const context = event.detail;
        const dataState = {
            key: context.owner.childDataKey,
            parentID: context.parentID,
            parentKey: _parentKey,
            rootLevel: false
        };
    
        context.grid.isLoading = true;
    
        getData(dataState).then((data: any[]) => {
            context.grid.isLoading = false;
            context.grid.data = data;
            context.grid.markForCheck();
        });
    }
    

    API References

    Additional Resources

    우리 커뮤니티는 활동적이며 항상 새로운 아이디어를 환영합니다.