Como usar o serviço de transação

    Você pode aproveitar o Transaction Service ao usar qualquer componente que precise preservar o estado de sua fonte de dados e confirmar muitas transações de uma só vez.

    Ao trabalhar com os componentes de grade Ignite UI for Angular, você pode usar o igxTransactionService e igxHierarchicalTransactionService que são integrados com as grades e fornecem edição em lote pronta para uso. No entanto, se você precisar usar transações com qualquer outro Ignite UI for Angular ou componente personalizado, você pode usar novamente o igxTransactionService e implementar um comportamento semelhante.

    Angular How to use the Transaction service Example

    Neste tópico, usaremos o componente igxList para demonstrar como habilitar transações. Demonstraremos como adicionar transações, como transformar os dados por meio de um pipe e como atualizar visualmente a visualização para permitir que o usuário veja as alterações que estão prestes a serem confirmadas.

    Include Transaction Service

    Include Transaction Service in project

    Temos duas opções para incluir IgxTransactionService em nossa aplicação. A primeira é adicioná-lo ao AppModule ou outro módulo pai na aplicação, como é feito na demonstração acima:

    @NgModule({
        ...
        providers: [
            IgxTransactionService
        ]
    })
    export class AppModule { }
    

    A outra opção é fornecê-lo no componente onde o serviço de transação é usado:

    @Component({
        selector: 'transaction-base',
        styleUrls: ['./transaction-base.component.scss'],
        templateUrl: 'transaction-base.component.html',
        providers: [IgxTransactionService]
    })
    export class TransactionBaseComponent { }
    

    Inject Transaction Service in component

    Em nosso arquivo ts, devemos importar igxTransactionService da biblioteca igniteui-angular, bem como as interfaces State e Transaction e a enumeração TransactionType, que serão necessárias para nossa aplicação:

    import { IgxTransactionService, State, Transaction, TransactionType } from 'igniteui-angular';
    // import { IgxTransactionService, State, Transaction, TransactionType } from '@infragistics/igniteui-angular'; for licensed package
    

    Então o Transaction Service deve ser importado no construtor:

    constructor(private _transactions: IgxTransactionService<Transaction, State>) { ... }
    

    Define igxList

    Em nosso modelo HTML, definimos um componente igxList com ações edit, delete e add, que modificam a lista e seus itens:

    <igx-list>
        <igx-list-item [isHeader]="true">Wishlist</igx-list-item>
        <igx-list-item *ngFor="let item of this.wishlist | transactionBasePipe"
            [ngClass]="{ deleted: isDeleted(item.id), edited: isEdited(item.id) }">
            <p igxListLineTitle>{{item.name}}</p>
            <p igxListLineSubTitle>Costs: {{item.price}}</p>
            <igx-icon igxListAction (click)="onEdit()" *ngIf="item.id === 1 && item.price !== '$999'">edit</igx-icon>
            <igx-icon igxListAction (click)="onDelete()" *ngIf="item.id === 2 && !isDeleted(item.id)">delete</igx-icon>
        </igx-list-item>
        <button igxButton (click)="onAdd()" [disabled]="itemAdded(4)">Add New</button>
    </igx-list>
    

    Pipe for pending changes

    O componente de lista acima usa o transactionBasePipe para exibir alterações nos itens na lista de desejos sem afetar os dados originais. Aqui está a aparência do pipe:

    @Pipe({
        name: 'transactionBasePipe',
        pure: false
    })
    export class TransactionBasePipe implements PipeTransform {
        /**
         * @param transactions Injected Transaction Service.
         */
        constructor(public transactions: IgxTransactionService<Transaction, State>) { }
    
        public transform(data: WishlistItem[]) {
            // the pipe should NOT operate on the original dataset
            // we create a copy of the original data and then use it for visualization only
            const _data = [...data];
            const pendingStates = this.transactions.getAggregatedChanges(false);
    
            for (const state of pendingStates) {
                switch (state.type) {
                    case TransactionType.ADD:
                        // push the newValue property of the current `ADD` state
                        _data.push(state.newValue);
                        break;
                    case TransactionType.DELETE:
                        // pipe doesn't delete items because the demo displays them with a different style
                        // the record will be deleted once the state is committed
                        break;
                    case TransactionType.UPDATE:
                        const index = _data.findIndex(x => x.id === state.id);
                        // merge changes with the item into a new object
                        // to avoid modifying the original data item
                        _data[index] = Object.assign({}, _data[index], state.newValue);
                        break;
                    default:
                        return _data;
                }
            }
    
            return _data;
        }
    }
    

    Edit, delete, add functionality

    Define edit functionality

    O segundo item da lista contém um botão de edição, que atualiza os dados do item.

    <igx-icon igxListAction (click)="onEdit()" *ngIf="item.id === 1 && item.price !== '$999'">edit</igx-icon>
    

    Quando o botão é pressionado, dentro do manipulador de eventos onEdit, uma transação 'UPDATE' é criada:

    public onEdit(): void {
        const newPrice = "$999";
        // there can be multiple `UPDATE` transactions for the same item `id`
        // the `newValue` property should hold only the changed properties
        const editTransaction: Transaction = {
            id: this.wishlist[0].id,
            type: TransactionType.UPDATE,
            newValue: { price: newPrice }
        };
        // provide the first wishlist item as a `recordRef` argument
        this.transactions.add(editTransaction, this.wishlist[0]);
    }
    

    Além disso, há uma função que verifica itens em busca de edições não salvas:

    public isEdited(id): boolean {
        const state = this.transactions.getState(id);
        return state && state.type === TransactionType.UPDATE;
    }
    

    Define delete functionality

    O terceiro item da lista contém um botão de exclusão, que exclui os dados do item.

    <igx-icon igxListAction (click)="onDelete()" *ngIf="item.id === 2 && !isDeleted(item.id)">delete</igx-icon>
    

    Quando o botão é pressionado, dentro do manipulador de eventos onDelete, uma transação 'DELETE' é criada:

    public onDelete(): void {
        // after a `DELETE` transaction, no further changes should be made for the same `id`
        // the `newValue` property should be set to `null` since we do not change any values,
        const deleteTransaction: Transaction = {
            id: this.wishlist[1].id,
            type: TransactionType.DELETE,
            newValue: null
        };
        // provide the second wishlist item as a `recordRef` argument
        this.transactions.add(deleteTransaction, this.wishlist[1]);
    }
    

    Além disso, há uma função que verifica se há itens excluídos não salvos:

    public isDeleted(id): boolean {
        const state = this.transactions.getState(id);
        return state && state.type === TransactionType.DELETE;
    }
    

    Define add functionality

    No final da lista, é adicionado um botão ADICIONAR, que adiciona um novo item à lista.

    <button igxButton (click)="onAdd()" [disabled]="itemAdded(4)">Add New</button>```
    

    Quando o botão é pressionado, dentro do manipulador de eventos onAdd, uma transação 'ADD' é criada:

    public onAdd(): void {
        // it must have a unique 'id' property
        const item: WishlistItem = { id: 4, name: 'Yacht', price: 'A lot!' };
    
        // in an `ADD` transaction you do not need to provide a `recordRef` argument,
        // since there is nothing to refer to yet
        this.transactions.add({ id: 4, type: TransactionType.ADD, newValue: item });
    }
    

    Além disso, há uma função que verifica itens em busca de adições não salvas:

    public itemAdded(id: number): boolean {
        const found = this.transactions.getState(id) || this.wishlist.find(x => x.id === 4);
        return !!found;
    }
    

    Transaction Log

    A demonstração demonstra as transações pendentes dentro de um log:

    <div>
        <h5>Transaction Log</h5>
        <div *ngFor="let transaction of this.getTransactionLog()">
            {{transaction.type.toUpperCase()}} -> {{transaction.name}} Costs: {{transaction.price}}
        </div>
    </div>
    
    public getTransactionLog(): any[] {
        return this.transactions.getTransactionLog().map(transaction => {
            const item = this.wishlist.find(x => x.id === transaction.id);
            return Object.assign({ type: transaction.type }, item, transaction.newValue);
        });
    }
    

    Também adicionaremos uma representação do estado atual da nossa lista. Ela mostrará como os dados parecem antes das transações pendentes serem confirmadas:

    <div>
        <h5>Data Items</h5>
        <div *ngFor="let item of this.wishlist">
            <div>{{item.name}} - {{item.price}}</div>
        </div>
    </div>
    

    Commit pending transactions

    Assim que terminarmos todas as nossas alterações, podemos comprometê-las todas de uma vez usando o método commit do igxTransactionService. Ele aplica todas as transações sobre os dados fornecidos:

    <button igxButton="contained" (click)="onCommit()" [disabled]="this.getTransactionLog().length === 0">Commit Transactions</button>
    
    public onCommit(): void {
        // the `commit` function expects the original data array as its parameter
        this.transactions.commit(this.wishlist);
    }
    
    

    Se estivermos usando o igxHierarchicalTransactionService, também podemos usar uma sobrecarga do método commit que espera primaryKey e childDataKey como argumentos.

    public onCommit(): void {
        this.transactions.commit(this.wishlist, primaryKey, childDataKey);
    }
    

    Clear pending transactions

    Em qualquer ponto da nossa interação com a lista, podemos limpar o log de transações usando o método clear.

    <button igxButton="contained" (click)="onClear()" [disabled]="this.getTransactionLog().length === 0">Clear Transactions</button>
    
    public onClear(): void {
        this.transactions.clear();
    }
    
    

    Additional Resources