Carga de grade hierárquica sob demanda

    O Ignite UI for Web Components IgcHierarchicalGridComponent permite uma renderização rápida, solicitando a quantidade mínima de dados a serem recuperados do servidor para que o usuário possa ver o resultado em exibição e interagir com os dados visíveis o mais rápido possível. Inicialmente, apenas os dados da grade raiz são recuperados e renderizados, somente depois que o usuário expandir uma linha contendo uma grade filho, ele receberá os dados dessa grade filho específica. Esse mecanismo, também conhecido como Load on Demand, pode ser facilmente configurado para funcionar com qualquer dado remoto.

    Este tópico demonstra como configurar a Carga sob Demanda criando um Provedor de Serviços Remotos que se comunica com um serviço remoto já disponível. Aqui está a demonstração de trabalho e, mais tarde, vamos analisá-la passo a passo e descrever o processo de criação.

    Web Components Hierarchical Grid Load On Demand Example

    Remote Service Provider

    Primeiro, prepararemos nosso provedor de serviços para que estejamos prontos para obter os dados necessários para a grade hierárquica.

    Obtendo dados básicos

    Estaremos nos comunicando com nosso serviço de back-end pelo protocolo HTTP usando a fetch() função global que os navegadores fornecem. Dessa forma, para obter nossos dados, precisaremos deste método simples em nosso serviço:

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

    Como você pode ver buildUrl(), será o método que gerará nossa url com base nos dados que recebemos. Retornamos uma promessa, pois ela é executada de forma assíncrona. Dessa forma, podemos subscrevê-lo posteriormente, processá-lo ainda mais em nosso aplicativo e passá-lo para nossa grade.

    Construindo nossa URL de solicitação

    Em seguida, definiremos como devemos construir nossa URL para a solicitação GET. É aqui que poderemos obter os dados para nossa grade principal, mas também para qualquer grade secundária dentro dela. Usaremos os Customers dados daqui para nosso nível raiz e uso Orders e Details para os níveis inferiores. O modelo será diferente por aplicativo, mas usaremos o seguinte:

    O que precisamos primeiro é da key nossa tabela para determinar de onde obter os dados para a grade desejada, a chave primária da linha pai e seu ID exclusivo.

    Vamos definir tudo isso no dataState objeto. Um exemplo:

    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}`;
    }
    

    Resultado

    Finalmente, é assim que nosso serviço remoto seria:

    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

    Em seguida, configuraremos nossa grade hierárquica e a conectaremos ao nosso provedor de serviços remotos.

    Definição de modelo

    Primeiro, definiremos nosso modelo de grade hierárquica com os níveis de hierarquia que esperamos ter. Sabemos que nossa grade PrimaryKey raiz para os clientes é deles customerId, para seus pedidos no primeiro nível -orderId e respectivamente para detalhes do pedido -productId. Conhecer cada tabela de banco de dados e suas chaves nos permite definir nosso modelo inicial:

    <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>
    

    No entanto, há uma coisa faltando em nosso modelo, que são os dados para nossa grade hierárquica de nível raiz e, eventualmente, seus filhos.

    Definiremos facilmente os dados da grade raiz depois de obter seus dados do serviço em nosso código posteriormente, pois podemos usar a id="hGrid" referência.

    Definir os dados para qualquer filho que foi expandido é um pouco diferente. Quando uma linha é expandida pela primeira vez, um novo filho IgcHierarchicalGridComponent é renderizado para ela e precisamos obter a referência da grade recém-criada para definir seus dados. É por isso que cada IgcRowIsland componente fornece o GridCreated evento que é acionado quando uma nova grade filho é criada para essa ilha de linha específica. Podemos usar isso para obter a referência necessária para a nova grade, solicitar seus dados do serviço e aplicá-los.

    Podemos usar um método para todas as ilhas de linha, já que construímos nosso serviço de modo que ele precise apenas de informações se for o nível raiz, a chave da ilha de linha, a chave primária da linha pai e seu identificador exclusivo. Todas essas informações podem ser acessadas diretamente dos argumentos do evento ou da ilha de linha responsável por disparar o evento.

    Vamos nomear o método que usaremos gridCreated.

    Como o GridCreated evento fornece a parentID propriedade, uma referência à ilha de linha como owner e à nova propriedade filho grid, ela será passada como o primeiro argumento. Faltam apenas informações sobre a linha primaryKey pai, mas podemos facilmente passar isso como um segundo argumento, dependendo de qual ilha de linha vinculamos.

    O arquivo de modelo, com essas alterações adicionadas, ficaria assim:

    <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");
        });
    }
    

    Conectando nosso serviço

    Uma de nossas etapas finais agora será conectar nosso serviço criado anteriormente à nossa grade hierárquica.

    Obteremos uma referência à nossa grade raiz para definir seus dados. Como não tem pais, só podemos passar o que rootLevel é verdade, e a chave para isso, para o getData nosso serviço. Como ele retorna uma promessa, precisaremos assiná-la:

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

    Em seguida, precisamos apenas criar nosso gridCreated método que solicitará dados para qualquer nova grade filha criada.

    Será semelhante a obter os dados da grade de nível raiz, só que desta vez precisaremos passar mais informações, como parentID e parentKey. rootLevel será falso para qualquer criança:

    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();
        });
    }
    

    Com isso, a configuração do nosso aplicativo está quase pronta. Esta última etapa visa melhorar a experiência do usuário, informando ao usuário que os dados ainda estão sendo carregados para que ele não precise olhar para uma grade vazia enquanto isso. É por isso que o suporta IgcHierarchicalGridComponent um indicador de carga que pode ser exibido enquanto a grade está vazia. Se novos dados forem recebidos, o indicador de carregamento será ocultado e os dados serão renderizados.

    Configuração da indicação de carga

    O IgcHierarchicalGridComponent pode exibir um indicador de carregamento definindo a IsLoading propriedade como true enquanto não houver dados. Precisamos configurá-lo inicialmente para a grade raiz e também ao criar novas grades filhas, até que seus dados sejam carregados. Sempre podemos defini-lo como true em nosso modelo, mas queremos ocultá-lo e exibir que a grade não tem dados se o serviço retornar uma matriz vazia definindo-a como false.

    Nesse caso, a versão final de nossa configuração ficaria assim:

    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

    Nossa comunidade é ativa e sempre acolhedora para novas ideias.