Cómo utilizar el servicio de transacciones
Puede aprovechar el Transaction Service
cuando utilice cualquier componente que necesite preservar el estado de su fuente de datos y realizar muchas transacciones a la vez.
Al trabajar con los componentes de cuadrícula Ignite UI for Angular, puede utilizar el igxTransactionService
y igxHierarchicalTransactionService
que están integrados con las cuadrículas y proporcionan edición por lotes lista para usar. Sin embargo, si necesita usar transacciones con cualquier otro componente Ignite UI for Angular o personalizado, puede volver a usar el e implementar un igxTransactionService
comportamiento similar.
Angular Cómo utilizar el servicio de transacciones Ejemplo
En este tema usaremos el componente igxList
para demostrar cómo habilitar transacciones. Demostraremos cómo agregar transacciones, cómo transformar los datos a través de una tubería y cómo actualizar visualmente la vista para permitir al usuario ver los cambios que están a punto de confirmarse.
¿Te gusta esta muestra? Obtenga acceso a nuestro kit de herramientas de Ignite UI for Angular completo y comience a crear sus propias aplicaciones en minutos. Descárgalo gratis.
Incluir servicio de transacciones
Incluir el servicio de transacciones en el proyecto
Tenemos dos opciones para incluir IgxTransactionService
en nuestra aplicación. La primera es agregarlo a AppModule
u otro módulo principal en la aplicación, como se hace en la demostración anterior:
@NgModule({
...
providers: [
IgxTransactionService
]
})
export class AppModule { }
typescript
La otra opción es proporcionarlo en el componente donde se utiliza el servicio de transacciones:
@Component({
selector: 'transaction-base',
styleUrls: ['./transaction-base.component.scss'],
templateUrl: 'transaction-base.component.html',
providers: [IgxTransactionService]
})
export class TransactionBaseComponent { }
typescript
Inyectar servicio de transacciones en el componente
En nuestro archivo ts
, debemos importar igxTransactionService
de la biblioteca igniteui-angular
, así como las interfaces State
y Transaction
y la enumeración TransactionType
, que será necesaria para nuestra aplicación:
import { IgxTransactionService, State, Transaction, TransactionType } from 'igniteui-angular';
// import { IgxTransactionService, State, Transaction, TransactionType } from '@infragistics/igniteui-angular'; for licensed package
typescript
Luego, Transaction Service debe importarse en el constructor:
constructor(private _transactions: IgxTransactionService<Transaction, State>) { ... }
typescript
Definir igxList
En nuestra plantilla html, definimos un componente igxList
con acciones editar, eliminar y agregar, que modifican la lista y sus elementos:
<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>
html
Tubería para cambios pendientes
El componente de lista anterior utiliza transactionBasePipe
para mostrar cambios en los elementos de la lista de deseos sin afectar los datos originales. Así es como se ve la tubería:
@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;
}
}
typescript
Editar, eliminar, agregar funcionalidad
Definir la funcionalidad de edición
El segundo elemento de la lista contiene un botón de edición, que actualiza los datos del elemento.
<igx-icon igxListAction (click)="onEdit()" *ngIf="item.id === 1 && item.price !== '$999'">edit</igx-icon>
html
Cuando se presiona el botón, dentro del controlador de eventos onEdit
, se crea una transacción 'ACTUALIZAR':
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]);
}
typescript
Además, hay una función que verifica los elementos en busca de ediciones no guardadas:
public isEdited(id): boolean {
const state = this.transactions.getState(id);
return state && state.type === TransactionType.UPDATE;
}
typescript
Definir la funcionalidad de eliminación
El tercer elemento de la lista contiene un botón de eliminación, que elimina los datos del elemento.
<igx-icon igxListAction (click)="onDelete()" *ngIf="item.id === 2 && !isDeleted(item.id)">delete</igx-icon>
html
Cuando se presiona el botón, dentro del controlador de eventos onDelete
, se crea una transacción 'ELIMINAR':
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]);
}
typescript
Además, existe una función que comprueba si los elementos se han eliminado sin guardar:
public isDeleted(id): boolean {
const state = this.transactions.getState(id);
return state && state.type === TransactionType.DELETE;
}
typescript
Definir agregar funcionalidad
Al final de la lista se agrega un botón AGREGAR, que agrega un nuevo elemento a la lista.
<button igxButton (click)="onAdd()" [disabled]="itemAdded(4)">Add New</button>```
html
Cuando se presiona el botón, dentro del controlador de eventos onAdd
, se crea una transacción 'ADD':
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 });
}
typescript
Además, hay una función que comprueba si hay elementos añadidos no guardados:
public itemAdded(id: number): boolean {
const found = this.transactions.getState(id) || this.wishlist.find(x => x.id === 4);
return !!found;
}
typescript
Registro de transacciones
La demostración muestra las transacciones pendientes dentro de un registro:
<div>
<h5>Transaction Log</h5>
<div *ngFor="let transaction of this.getTransactionLog()">
{{transaction.type.toUpperCase()}} -> {{transaction.name}} Costs: {{transaction.price}}
</div>
</div>
html
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);
});
}
typescript
También agregaremos una representación del estado actual de nuestra lista. Mostrará cómo se ven los datos antes de que se confirmen las transacciones pendientes:
<div>
<h5>Data Items</h5>
<div *ngFor="let item of this.wishlist">
<div>{{item.name}} - {{item.price}}</div>
</div>
</div>
html
Confirmar transacciones pendientes
Una vez que hayamos terminado con todos nuestros cambios, podemos confirmarlos todos a la vez usando el método commit
de igxTransactionService
. Aplica todas las transacciones sobre los datos proporcionados:
<button igxButton="contained" (click)="onCommit()" [disabled]="this.getTransactionLog().length === 0">Commit Transactions</button>
html
public onCommit(): void {
// the `commit` function expects the original data array as its parameter
this.transactions.commit(this.wishlist);
}
typescript
Si usamos igxHierarchicalTransactionService
también podemos usar una sobrecarga del método commit
que espera PrimaryKey y ChildDataKey como argumentos.
public onCommit(): void {
this.transactions.commit(this.wishlist, primaryKey, childDataKey);
}
typescript
Borrar transacciones pendientes
En cualquier punto de nuestra interacción con la lista, podemos borrar el registro de transacciones utilizando el método clear
.
<button igxButton="contained" (click)="onClear()" [disabled]="this.getTransactionLog().length === 0">Clear Transactions</button>
html
public onClear(): void {
this.transactions.clear();
}
typescript
Recursos adicionales
- API de servicio de transacciones
- Servicio de transacciones
- Jerarquía de clases de servicios de transacciones