Carga de grade hierárquica sob demanda

    O Ignite UI for AngularIgxHierarchicalGrid permite renderização rápida solicitando que a quantidade mínima de dados seja recuperada do servidor para que o usuário possa ver o resultado em vista e interagir com os dados visíveis o mais rapidamente possível. Inicialmente, apenas os dados da grade raiz são recuperados e renderizados; somente depois que o usuário expande uma linha contendo uma grade filha, ele receberá os dados para essa grade filha 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 o Load on Demand solicitando dados de uma WebAPI Northwind. Aqui está a demonstração de trabalho e, mais tarde, vamos analisá-la passo a passo e descrever o processo de criação.

    Angular Hierarchical Grid Load On Demand Example

    Hierarchical Grid Setup

    Vamos montar nossa grade hierárquica. Primeiro, definiremos nosso modelo de grade hierárquica com os níveis de hierarquia que esperamos ter. Sabemos que nossa gradeprimaryKey raiz para os clientes é delescustomerId, para seus pedidos no primeiro nível —orderIde, respectivamente, para detalhes dos pedidos —productId. Conhecer cada tabela de banco de dados e suas chaves nos permite definir nosso modelo inicial:

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

    Vamos definir facilmente os dados da grade raiz depois de obter os dados do endpoint em nosso código depois, já que podemos usar a#hGrid referência. Definir os dados para qualquer filho que foi expandido é um pouco diferente.

    Quando uma linha é expandida pela primeira vez, um novo filhoIgxHierarchicalGrid é renderizado para ela e precisamos obter a referência da grade recém-criada para definir seus dados. Por isso, cadaIgxRowIsland componente fornece ogridCreated evento que é disparado quando uma nova grade filha é criada para aquela ilha de linha específica. Podemos usar isso para obter a referência necessária para a nova grade, solicitar seus dados do endpoint e aplicá-los.

    Podemos usar um método para todas as ilhas de linha, pois o endpoint só precisa da chave da ilha de linha, da chave primária da linha pai e de seu identificador exclusivo. Todas essas informações podem ser acessadas diretamente dos argumentos do evento.

    Configuração da indicação de carga

    Agora vamos melhorar a experiência do usuário informando que os dados ainda estão carregando, para que ele não precise olhar para uma grade vazia enquanto isso. Por isso, eleIgxHierarchicalGrid suporta um indicador de carregamento que pode ser exibido enquanto a grade está vazia.

    Exibimos um indicador de carregamento definindo aisLoading propriedade paratrue enquanto não há dados. Precisamos definir inicialmente para a grade raiz e também, ao criar novas grades filhas, até que os dados sejam carregados. Sempre poderíamos definir paratrue no nosso template, mas queremos esconder (configurando parafalse) e mostrar que a grade não tem dados se o serviço devolver um array vazio.

    Por fim, vamos desligar aautoGenerate propriedade e definir a coleção de colunas na marcação.

    O arquivohierarchical-grid-lod.component.html modelo, após todas as mudanças adicionadas, ficaria assim:

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

    Advanced filtering

    Para usar Filtragem Avançada comIgxHierarchicalGrid carga sob demanda, você precisa definir aschema propriedade da grade para uma entidade com estrutura hierárquica, especificando entidades e campos filhos com seus tipos de dados. Isso garante que expressões de filtragem com consultas aninhadas possam ser criadas mesmo antes de qualquer dado da grade filha ser carregado e que a grade possa interpretar e aplicar corretamente esses filtros aos dados.

    No nosso caso, esta é a estrutura hierárquica correta:

    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' }
                            ]
                        }
                    ]
                }
            ]
        }
    ];
    

    Configurando o filtro inicial

    Agora vamos adicionar regras iniciais de filtragem à nossa grade para que a grade raiz seja filtrada quando carregada pela primeira vez. Vamos criar umFilteringExpressionsTree e defini-lo para aadvancedFilteringExpressionsTree propriedade de usandoIgxHierarchicalGrid ongOnInit gancho do ciclo de vida.

    Digamos que queremos filtrar clientes que têm pelo menos o frete500 do pedido. Vamos aproveitar a capacidade de criar consultas aninhadas nas expressões de filtragem e este é o resultado:

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

    Connecting to the endpoint

    Vamos nos comunicar com o endpoint via protocolo HTTP usando a interface XMLHttpRequest que os navegadores fornecem. Para facilitar isso, usaremos o módulo doHttpClient Angular que oferece uma API HTTP de cliente simplificada.

    Obtendo dados da grade raiz

    A Northwind WebAPI nos fornece um endpoint POST que aceita umIFilteringExpressionsTree como parâmetro e o usaremos para aproveitar a funcionalidade de Filtragem Avançada nosIgxHierarchicalGrid registros de filtro e na grade raiz. Faremos isso de formarefreshRootGridData semelhante:

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

    Como você pode ver,this.http será uma referência ao nossoHttpCLient módulo. Osubscribe método faz parte do Observable de Angular e é usado para lidar com a resposta assíncrona da requisição HTTP. Quando os dados são recebidos, ele os atribui à grade relevante, atualiza seu estado de carregamento para falso e aciona a detecção de mudanças para garantir que a interface reflita as alterações.

    Para carregar os dados após a grade raiz ser inicialmente renderizada, usaremos ongAfterViewInit gancho do ciclo de vida e chamaremos orefreshRootGridData método:

    public ngAfterViewInit() {
        this.refreshRootGridData();
    }
    

    Obtendo dados de grades filho

    Em seguida, definiremos como devemos criar nossa URL para a solicitação GET para obter os dados de nossas grades filhas. Esta é a representação visual das relações entre as tabelas:

    Banco de Dados Hierárquico Relacional

    Por fim, precisamos implementar nossogridCreated método que solicitará dados para qualquer nova grade filha criada. Será semelhante a obter os dados da grade em nível raiz, só que desta vez usaremos os dados fornecidos no eventogridCreated e construiremos nossa URL com eles:

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

    API References

    Additional Resources

    Nossa comunidade é ativa e sempre acolhedora para novas ideias.