Carga de grade hierárquica sob demanda

    O Ignite UI for React IgrHierarchicalGrid 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.

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

    Getting basic data

    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 async function getData(dataState: any): Promise<any> {
        const response = await fetch(buildUrl(dataState));
        const data = await response.json();
        return data;
    }
    

    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.

    Building our request url

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

    Result

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

    const URL = `https://data-northwind.indigo.design/`;
    
    export async function getData(dataState: any): Promise<any> {
        const response = await fetch(buildUrl(dataState));
        const data = await response.json();
        return data;
    }
    
    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.

    Template defining

    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:

    <IgrHierarchicalGrid ref={hierarchicalGrid} primaryKey="customerId" height="600px">
        <IgrColumn field="customerId" hidden={true}></IgrColumn>
        <IgrColumn field="companyName" header="Company Name"></IgrColumn>
        <IgrColumn field="contactName" header="Contact Name"></IgrColumn>
        <IgrColumn field="contactTitle" header="Contact Title"></IgrColumn>
        <IgrColumn field="address.country" header="Country"></IgrColumn>
        <IgrColumn field="address.phone" header="Phone"></IgrColumn>
        <IgrRowIsland childDataKey="Orders" primaryKey="orderId">
            <IgrColumn field="orderId" hidden={true}></IgrColumn>
            <IgrColumn field="shipAddress.country" header="Ship Country"></IgrColumn>
            <IgrColumn field="shipAddress.city" header="Ship City"></IgrColumn>
            <IgrColumn field="shipAddress.street" header="Ship Address"></IgrColumn>
            <IgrColumn field="orderDate" header="Order Date" dataType="date"></IgrColumn>
            <IgrRowIsland childDataKey="Details" primaryKey="productId">
                <IgrColumn field="productId" hidden={true}></IgrColumn>
                <IgrColumn field="quantity" header="Quantity"></IgrColumn>
                <IgrColumn field="unitPrice" header="Unit Price"></IgrColumn>
                <IgrColumn field="discount" header="Discount"></IgrColumn>
            </IgrRowIsland>
        </IgrRowIsland>
    </IgrHierarchicalGrid>
    

    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 ref={hierarchicalGrid} referência.

    Definir os dados para qualquer filho que foi expandido é um pouco diferente. Quando uma linha é expandida pela primeira vez, um novo filho IgrHierarchicalGrid é renderizado para ela e precisamos obter a referência da grade recém-criada para definir seus dados. É por isso que cada IgrRowIsland 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 uma referência à ilha de linha, à parentID propriedade e à nova propriedade filho grid, isso será passado como o primeiro e o segundo argumentos. Faltam apenas informações sobre as linhas primaryKey pai, mas podemos facilmente passar isso como um terceiro argumento, dependendo de qual ilha de linha vinculamos.

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

    <IgrHierarchicalGrid ref={hierarchicalGrid} primaryKey="customerId" height="600px">
        <IgrColumn field="customerId" hidden={true}></IgrColumn>
        <IgrColumn field="companyName" header="Company Name"></IgrColumn>
        <IgrColumn field="contactName" header="Contact Name"></IgrColumn>
        <IgrColumn field="contactTitle" header="Contact Title"></IgrColumn>
        <IgrColumn field="address.country" header="Country"></IgrColumn>
        <IgrColumn field="address.phone" header="Phone"></IgrColumn>
        <IgrRowIsland childDataKey="Orders" primaryKey="orderId" onGridCreated={(e: IgrGridCreatedEventArgs) => gridCreated(e, "Customers")}>
            <IgrColumn field="orderId" hidden={true}></IgrColumn>
            <IgrColumn field="shipAddress.country" header="Ship Country"></IgrColumn>
            <IgrColumn field="shipAddress.city" header="Ship City"></IgrColumn>
            <IgrColumn field="shipAddress.street" header="Ship Address"></IgrColumn>
            <IgrColumn field="orderDate" header="Order Date" dataType="date"></IgrColumn>
            <IgrRowIsland childDataKey="Details" primaryKey="productId" onGridCreated={(e: IgrGridCreatedEventArgs) => gridCreated(e, "Orders")}>
                <IgrColumn field="productId" hidden={true}></IgrColumn>
                <IgrColumn field="quantity" header="Quantity"></IgrColumn>
                <IgrColumn field="unitPrice" header="Unit Price"></IgrColumn>
                <IgrColumn field="discount" header="Discount"></IgrColumn>
            </IgrRowIsland>
        </IgrRowIsland>
    </IgrHierarchicalGrid>
    

    Connecting our service

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

    Obteremos uma referência à nossa grade raiz por meio do useRef gancho React para definir seus dados:

    const hierarchicalGrid = useRef<IgrHierarchicalGrid>(null);
    

    Para garantir que nossa grade seja renderizada antes de solicitarmos seus dados do serviço e atribuí-los, usaremos o useEffect gancho React. 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:

    useEffect(() => {
        getData({ parentID: null, rootLevel: true, key: "Customers" }).then(
          (data: any) => {
            hierarchicalGrid.current.data = data;
            hierarchicalGrid.current.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:

    function gridCreated(event: IgrGridCreatedEventArgs, _parentKey: string) {
        const context = event.detail;
        const rowIsland = context.owner;
        const dataState = {
            key: rowIsland.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 IgrHierarchicalGrid 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.

    Setup of loading indication

    O IgrHierarchicalGrid 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:

    const hierarchicalGrid = useRef<IgrHierarchicalGrid>(null);
    
    useEffect(() => {
        hierarchicalGrid.current.isLoading = true;
        
        getData({ parentID: null, rootLevel: true, key: "Customers" }).then(
          (data: any) => {
            hierarchicalGrid.current.isLoading = false;
            hierarchicalGrid.current.data = data;
            hierarchicalGrid.current.markForCheck();
        }
      );
    }, []);
    
    function gridCreated(event: IgrGridCreatedEventArgs, _parentKey: string) {
        const context = event.detail;
        const rowIsland = context.owner;
        const dataState = {
            key: rowIsland.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.