Jerarquía de clases de servicios de transacciones

    Transaction, State, Transaction Log

    The Transaction is the main building block of the Transaction service. The Transaction is actually every operation that you execute on the data. The Transaction interface defines three properties: id, newValue and type.

    The id of the Transaction should be unique per data record and defines the record that this transaction is affecting. The type may be any of the three transaction types: ADD, DELETE and UPDATE, depending what operation you execute. The newValue contains the value of the new record in case you are adding an ADD transaction. If you are updating an existing record, the newValue would contain the changes only. You may have several transactions of UPDATE type with same id. If you are deleting a record, the newValue will contain the value of the deleted record.

    Puede ver un ejemplo de cómo se ve agregar cada tipo de transacción en el tema Cómo utilizar el servicio de transacciones.

    Every time you add a Transaction, it is added to the transaction log and undo stack. All the changes in the transaction log are then accumulated per record. From that point, the service maintains an aggregated State. The State consists of unique records and every record may be of one of the supported transaction types, mentioned above.

    While adding transactions you may turn on pending transactions by calling startPending. All subsequent transactions will be accumulated in single transaction until you call endPending. If you pass true to endPending all accumulated transactions will be added as a single transaction in the transaction log and in the undo stack.

    Using igxBaseTransaction

    Our grid module provides a very basic implementation of the Transaction service (igxBaseTransactionService) with just pending session functionality allowing for Row Editing feature. By using startPending and endPending Row editing can combine multiple per-cell operations into a single change. This means editing multiple cells of a single record creates a single transaction and you can handle just the row edit event.

    Dado que el estado acumulado es un objeto parcial, también podemos usar el servicio para verificar qué celda se ha editado y crear una interfaz de usuario en torno a eso.

    The igxBaseTransactionService has no undo stack so it does not provide undo/redo functionality.

    A detailed example of how you may use igxBaseTransactionService to enable Row Editing is provided in the following topics:

    General information on igxTransactionService and igxHierarchicalTransactionService

    igxTransactionService and igxHierarchicalTransactionService are injectable middlewares, that implement the Transaction Service interface. A component may use those to accumulate changes without affecting the underlying data. The provider exposes API to access, manipulate (undo and redo) and discard or commit one or all changes to the data.

    In a more concrete example, igxTransactionService and igxHierarchicalTransactionService can work with both cell editing and row editing of the IgxGrid. The transaction for the cell edit is added when the cell exits edit mode. When row editing starts the grid sets its transaction service in pending state by calling startPending. Each edited cell is added to the pending transaction log and is not added to the main transaction log. When the row exits edit mode all the changes are added to the main transaction log and to the undo log as a single transaction.

    En ambos casos (edición de celdas y edición de filas), el estado de las ediciones de la cuadrícula consta de todas las filas actualizadas, agregadas y eliminadas y sus últimos estados. Posteriormente, estos pueden inspeccionarse, manipularse y enviarse de una vez o por identificación. Los cambios se recopilan para celdas o filas individuales, según el modo de edición, y se acumulan por fila/registro de datos.

    Using igxTransactionService

    igxTransactionService extends igxBaseTransactionService.

    If you want your component to use transactions when making data operation, you need to define the igxTransactionService as a provider in your component's providers array.

    The igxTransactionService provides an undo stack so you may get advantage of the undo/redo functionality. The Undo stack is actually an array that contains arrays of transactions. When using the igxTransactionService, you may check the canUndo accessor in order to understand if there are any transactions in the Undo stack. If there are - you may use the undo method to remove the last transaction and redo to apply the last undone transaction.

    Puede encontrar un ejemplo detallado de cómo se implementa igxGrid con edición por lotes en el siguiente tema:

    Using igxHierarchicalTransactionService

    igxHierarchicalTransactionService extends igxTransactionService.

    The igxHierarchicalTransactionService is designed to handle the relations between parents and children (use this when you have a hierarchical data structure, as in igxTreeGrid, for example). The service ensures that a new record will be added to the place you expect when adding an ADD transaction. When you delete a parent record, its' children will be promoted to the higher level of hierarchy, or will be deleted with their parent, depending on implementation. You can see the cascadeOnDelete property of the tree grid for a concrete example - depending on the value, deleting a parent record will have different effects on its children.

    En su aplicación, es posible que desee manejar el escenario en el que el usuario intenta agregar un registro secundario a un registro principal que ya está eliminado y está esperando que se confirme la transacción. El Servicio de transacciones no permitirá agregar un registro a un padre que se va a eliminar y se mostrará un mensaje de error en la Consola. Sin embargo, puede verificar si se va a eliminar un padre e implementar su propia alerta para el usuario usando el siguiente código:

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

    You may find a detailed examples of how igxTreeGrid and igxHierarchicalGrid with Batch Editing are implemented in the following topics:

    Transaction Factory

    In the concrete implementation of transactions inside of Ignite UI for Angular grids, a factory is used in order to instantiate the proper transaction service, depending on the value of the grid's batchEditing. There are two separate transaction factories - the IgxFlatTransactionFactory (used for Grid and Hierarchical Grid) and IgxHierarchicalTransactionFactory (used for Tree Grid). Both classes expose only one method - create - which returns a new instance of the proper type. The parameter passed (TRANSACTION_TYPE) is internally used - None is used when batchEditing is false and Base - when batch editing is enabled. An enum is used (instead of a true - false flag), as it allows to be expanded upon.

    Using Transaction Factory

    Both IgxFlatTransactionFactory and IgxHierarchicalTransactionFactory are provided in root and are exposed in the public API. If you want to instantiate a new instance of a transaction service, depending on some arbitrary check, you can use a transaction factory.

    In the below example, you can see how you can instantiate different transaction services depending on an arbitrary (hasUndo) flag:

    import { IgxFlatTransactionFactory, TRANSACTION_TYPE } from 'igniteui-angular/core';
    // 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);
            }
        }
    }
    

    Both factory classes can be extended and overridden in the DI hierarchy (using the providers array) in order to provide your own, custom implementation. This, combined with the fact that all of the classes the get instantiated by the factories are also public, gives you a lot of control over what's provided to the components that use transaction implementations internally.

    For example, to override the transaction service used internally by the IgxGridComponent, you can do the following:

    Primero, defina una clase de fábrica personalizada

    import { IgxFlatTransactionFactory, TRANSACTION_TYPE, IgxBaseTransactionService,
    TransactionService, Transaction, State } from 'igniteui-angular/core';
    // 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);
        }
    }
    
    

    Then, in your component's providers array, override the IgxFlatTransactionFactory (used by igx-grid) with your custom implementation.

    import { IgxFlatTransactionFactory } from 'igniteui-angular/core';
    // 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 {
        ...
    }
    

    Now, when batchEditing is set to true, the grid will receive an instance of CustomTransactionService.

    Additional Resources