Hierarquia de classe do Serviço de Transação

    Transaction, State, Transaction Log

    A Transaction é o principal bloco de construção do serviço Transaction. A Transaction é, na verdade, toda operação que você executa nos dados. A interface Transaction define três propriedades: id, newValue e type.

    O id da transação deve ser único por registro de dados e define o registro que esta transação está afetando. O type pode ser qualquer um dos três tipos de transação: ADD, DELETE e UPDATE, dependendo de qual operação você executar. O newValue contém o valor do novo registro caso você esteja adicionando uma transação ADD. Se você estiver atualizando um registro existente, o newValue conterá apenas as alterações. Você pode ter várias transações do tipo UPDATE com o mesmo id. Se você estiver excluindo um registro, o newValue conterá o valor do registro excluído.

    Você pode ver um exemplo de como adicionar cada tipo de transação no tópico Como usar o serviço de transação.

    Toda vez que você adiciona uma Transaction, ela é adicionada ao log de transações e à pilha de desfazer. Todas as alterações no log de transações são então acumuladas por registro. A partir desse ponto, o serviço mantém um State agregado. O State consiste em registros exclusivos e cada registro pode ser de um dos tipos de transação suportados, mencionados acima.

    Ao adicionar transações, você pode ativar transações pendentes chamando startPending. Todas as transações subsequentes serão acumuladas em uma única transação até que você chame endPending. Se você passar true para endPending todas as transações acumuladas serão adicionadas como uma única transação no log de transações e na pilha de desfazer.

    Using igxBaseTransaction

    Nosso módulo de grade fornece uma implementação muito básica do serviço de transação (igxBaseTransactionService) com apenas a funcionalidade de sessão pendente, permitindo o recurso de edição de linha. Ao usar startPending e endPending, a edição de linha pode combinar várias operações por célula em uma única alteração. Isso significa que a edição de várias células de um único registro cria uma única transação e você pode manipular apenas o evento de edição de linha.

    Como o estado acumulado é um objeto parcial, também podemos usar o serviço para verificar qual célula foi editada e criar uma interface de usuário em torno disso.

    O igxBaseTransactionService não tem pilha de desfazer, portanto não fornece funcionalidade de desfazer/refazer.

    Um exemplo detalhado de como você pode usar igxBaseTransactionService para habilitar a edição de linha é fornecido nos seguintes tópicos:

    General information on igxTransactionService and igxHierarchicalTransactionService

    igxTransactionService e igxHierarchicalTransactionService são middlewares injetáveis, que implementam a interface Transaction Service. Um componente pode usá-los para acumular alterações sem afetar os dados subjacentes. O provedor expõe a API para acessar, manipular (desfazer e refazer) e descartar ou confirmar uma ou todas as alterações nos dados.

    Em um exemplo mais concreto, igxTransactionService e igxHierarchicalTransactionService podem trabalhar com edição de células e edição de linhas do IgxGrid. A transação para a edição de células é adicionada quando a célula sai do modo de edição. Quando a edição de linhas começa, a grade define seu serviço de transações em estado pendente chamando startPending. Cada célula editada é adicionada ao log de transações pendentes e não é adicionada ao log de transações principal. Quando a linha sai do modo de edição, todas as alterações são adicionadas ao log de transações principal e ao log de desfazer como uma única transação.

    Em ambos os casos (edição de células e edição de linhas), o estado das edições da grade consiste em todas as linhas atualizadas, adicionadas e excluídas e seus últimos estados. Elas podem ser inspecionadas, manipuladas e enviadas posteriormente de uma vez ou por id. As alterações são coletadas para células ou linhas individuais, dependendo do modo de edição, e acumuladas por linha/registro de dados.

    Using igxTransactionService

    igxTransactionService estende igxBaseTransactionService.

    Se você quiser que seu componente use transações ao fazer operações de dados, você precisa definir o igxTransactionService como um provedor na matriz de providers do seu componente.

    O igxTransactionService fornece uma pilha de desfazer para que você possa aproveitar a funcionalidade de desfazer/refazer. A pilha de desfazer é, na verdade, uma matriz que contém matrizes de transações. Ao usar o igxTransactionService, você pode verificar o acessador canUndo para entender se há alguma transação na pilha de desfazer. Se houver, você pode usar o método undo para remover a última transação e redo para aplicar a última transação desfeita.

    Você pode encontrar um exemplo detalhado de como o igxGrid com edição em lote é implementado no seguinte tópico:

    Using igxHierarchicalTransactionService

    igxHierarchicalTransactionService estende igxTransactionService.

    O igxHierarchicalTransactionService é projetado para manipular as relações entre pais e filhos (use isso quando você tiver uma estrutura de dados hierárquica, como em igxTreeGrid, por exemplo). O serviço garante que um novo registro será adicionado ao lugar que você espera ao adicionar uma transação ADD. Quando você exclui um registro pai, seus filhos serão promovidos para o nível mais alto da hierarquia ou serão excluídos com seus pais, dependendo da implementação. Você pode ver a propriedade cascadeOnDelete da grade de árvore para um exemplo concreto - dependendo do valor, excluir um registro pai terá efeitos diferentes em seus filhos.

    Em seu aplicativo, você pode querer lidar com o cenário em que o usuário tenta adicionar um registro filho a um registro pai que já foi excluído e está esperando a transação ser confirmada. O Transaction Service não permitirá adicionar um registro a um pai que deve ser excluído e uma mensagem de erro será exibida no Console. No entanto, você pode verificar se um pai deve ser excluído e implementar seu próprio alerta para o usuário usando o seguinte código:

        const state = this.transactions.getState(parentRecordID);
        if (state && state.type === TransactionType.DELETE) {
            // Implement your logic here
        }
    

    Você pode encontrar exemplos detalhados de como igxTreeGrid e igxHierarchicalGrid com edição em lote são implementados nos seguintes tópicos:

    Transaction Factory

    Na implementação concreta de transações dentro do Ignite UI for Angular, uma fábrica é usada para instanciar o serviço de transação apropriado, dependendo do valor do batchEditing da grade. Existem duas fábricas de transação separadas - a IgxFlatTransactionFactory (usada para Grid e Hierarchical Grid) e IgxHierarchicalTransactionFactory (usada para Tree Grid). Ambas as classes expõem apenas um método -create- que retorna uma nova instância do tipo apropriado. O parâmetro passado (TRANSACTION_TYPE) é usado internamente -None é usado quando batchEditing é false e Base- quando a edição em lote está habilitada. Um enum é usado (em vez de um sinalizador true-false), pois permite ser expandido.

    Using Transaction Factory

    Tanto IgxFlatTransactionFactory quanto IgxHierarchicalTransactionFactory são fornecidos na root e são expostos na API pública. Se você quiser instanciar uma nova instância de um serviço de transação, dependendo de alguma verificação arbitrária, você pode usar uma fábrica de transações.

    No exemplo abaixo, você pode ver como instanciar diferentes serviços de transação dependendo de um sinalizador arbitrário (hasUndo):

    import { IgxFlatTransactionFactory, TRANSACTION_TYPE } from 'igniteui-angular';
    // import { IgxFlatTransactionFactory, TRANSACTION_TYPE } from '@infragistics/igniteui-angular'; for licensed package
    
    export class MyCustomComponent {
        ...
        constructor(private transactionFactory: IgxFlatTransactionFactory) {}
        ...
        public transaction!: IgxTransactionService<Transaction, State>;
    
        public set hasUndo(val: boolean) {
            if (val) {
                this.transactions = this.transactionFactory.create(TRANSACTION_TYPE.Base);
            } else {
                this.transactions = this.transactionFactory.create(TRANSACTION_TYPE.None);
            }
        }
    }
    

    Ambas as classes de fábrica podem ser estendidas e substituídas na hierarquia DI (usando o array providers) para fornecer sua própria implementação personalizada. Isso, combinado com o fato de que todas as classes que são instanciadas pelas fábricas também são públicas, dá a você muito controle sobre o que é fornecido aos componentes que usam implementações de transação internamente.

    Por exemplo, para substituir o serviço de transação usado internamente pelo IgxGridComponent, você pode fazer o seguinte:

    Primeiro, defina uma classe de fábrica personalizada

    import { IgxFlatTransactionFactory, TRANSACTION_TYPE, IgxBaseTransactionService,
    TransactionService, Transaction, State } from 'igniteui-angular';
    // import { IgxFlatTransactionFactory, TRANSACTION_TYPE, IgxBaseTransactionService,
    // TransactionService, Transaction, State } from '@infragistics/igniteui-angular'; for licensed package
    
    class CustomTransactionService extends IgxBaseTransactionService {
        ...
    }
    
    export class CustomTransactionFactory extends IgxFlatTransactionFactory {
        ...
        create(type: TRANSACTION_TYPE): TransactionService<Transaction, State> {
            if (type === TRANSACTION_TYPE.Base) {
                return new CustomTransactionService();
            }
            super.create(type);
        }
    }
    
    

    Em seguida, na matriz de providers do seu componente, substitua o IgxFlatTransactionFactory (usado pelo igx-grid) pela sua implementação personalizada.

    import { IgxFlatTransactionFactory } from 'igniteui-angular';
    // import { IgxFlatTransactionFactory } from '@infragistics/igniteui-angular'; for licensed package
    import { CustomTransactionFactory } from '../custom-factory.ts';
    
    @Component({
        selector: 'app-grid-view',
        template: `<igx-grid [batchEditing]="true" [data]="data" [autoGenerate]="true"></igx-grid>`,
        providers: [{ provide: IgxFlatTransactionFactory, useClass: CustomTransactionFactory }]
    })
    
    export class GridViewComponent {
        ...
    }
    

    Agora, quando batchEditing estiver definido como true, a grade receberá uma instância de CustomTransactionService.

    Additional Resources