トランザクション サービスの使用方法
データソースの状態を保持し、一度に多くのトランザクションをコミットする必要があるコンポーネントを使用する場合、Transaction Service
を利用できます。
Ignite UI for Angular グリッドコンポーネントの igxTransactionService
と igxHierarchicalTransactionService
は、グリッドと統合して、追加設定なしに一括編集機能が使用できます。ただし、その他の Ignite UI for Angular またはカスタムコンポーネントでトランザクションを使用する必要がある場合は、再度 igxTransactionService
を使用して、同様の動作を実装できます。
Angular トランザクション サービスの使用方法の例
このトピックでは、igxList
コンポーネントを使用して、トランザクションを有効にする方法を示します。トランザクションを追加する方法、pipe を介してデータを変換する方法、およびコミットされようとしている変更をユーザーに表示するするためにビューを視覚的に更新する方法を示します。
トランザクション サービスを含む
トランザクション サービスをプロジェクトに含む
アプリケーションに IgxTransactionService
を含めるには、2 つのオプションがあります。最初の方法は、上記のデモで行われているように、アプリケーションの AppModule
または他の親モジュールに追加することです。
@NgModule({
...
providers: [
IgxTransactionService
]
})
export class AppModule { }
もう 1 つのオプションは、トランザクション サービスが使用されるコンポーネントで提供することです。
@Component({
selector: 'transaction-base',
styleUrls: ['./transaction-base.component.scss'],
templateUrl: 'transaction-base.component.html',
providers: [IgxTransactionService]
})
export class TransactionBaseComponent { }
コンポーネントにトランザクション サービスを注入する
ts
ファイルは、アプリケーションで必要となる igxTransactionService
を igniteui-angular
ライブラリからインポートし、State
および Transaction
インターフェイスと TransactionType
enum をインポートする必要があります。
import { IgxTransactionService, State, Transaction, TransactionType } from 'igniteui-angular';
// import { IgxTransactionService, State, Transaction, TransactionType } from '@infragistics/igniteui-angular'; for licensed package
次にトランザクション サービスをコンストラクターにインポートします。
constructor(private _transactions: IgxTransactionService<Transaction, State>) { ... }
igxList の定義
html テンプレートで igxList
コンポーネントに edit、delete、および add 処理を定義して、リストとそのアイテムを変更します。
<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>
保留中の変更のパイプ
上記のリスト コンポーネントは、transactionBasePipe
を使用して、元のデータに影響を与えることなく、ウィッシュ リスト内のアイテムへの変更を表示します。パイプは以下のようになります。
@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;
}
}
編集、削除、機能の追加
編集機能の定義
2 番目のリスト アイテムには、アイテムのデータを更新する編集ボタンが含まれています。
<igx-icon igxListAction (click)="onEdit()" *ngIf="item.id === 1 && item.price !== '$999'">edit</igx-icon>
onEdit
イベント ハンドラー内でボタンが押されると、'UPDATE' トランザクションが作成されます。
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]);
}
さらに、未保存の編集のアイテムをチェックする機能があります。
public isEdited(id): boolean {
const state = this.transactions.getState(id);
return state && state.type === TransactionType.UPDATE;
}
削除機能の定義
3 番目のリスト アイテムには、アイテムのデータを削除する削除ボタンが含まれています。
<igx-icon igxListAction (click)="onDelete()" *ngIf="item.id === 2 && !isDeleted(item.id)">delete</igx-icon>
onDelete
イベント ハンドラー内でボタンが押されると、'DELETE' トランザクションが作成されます。
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]);
}
さらに、保存されていない削除のアイテムをチェックする機能があります。
public isDeleted(id): boolean {
const state = this.transactions.getState(id);
return state && state.type === TransactionType.DELETE;
}
追加機能の定義
リストの最後に [追加] ボタンが追加され、リストに新しいアイテムが追加されます。
<button igxButton (click)="onAdd()" [disabled]="itemAdded(4)">Add New</button>```
onAdd
イベント ハンドラー内でボタンが押されると、'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 });
}
さらに、保存されていない追加項目をチェックする機能があります。
public itemAdded(id: number): boolean {
const found = this.transactions.getState(id) || this.wishlist.find(x => x.id === 4);
return !!found;
}
トランザクション ログ
デモでは、ログ内の保留中のトランザクションを示します。
<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);
});
}
リストの現在の状態の表現も追加します。保留中のトランザクションがコミットされる前のデータの様子を示します。
<div>
<h5>Data Items</h5>
<div *ngFor="let item of this.wishlist">
<div>{{item.name}} - {{item.price}}</div>
</div>
</div>
保留されたトランザクションをコミット
すべての変更が完了したら、igxTransactionService
の commit
メソッドを使用して、一度にすべてをコミットできます。指定されたデータにすべてのトランザクションを適用します。
<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);
}
igxHierarchicalTransactionService
を使用している場合は、primaryKey と childDataKey を引数として期待する commit
メソッドのオーバー読み込みを使用することもできます。
public onCommit(): void {
this.transactions.commit(this.wishlist, primaryKey, childDataKey);
}
保留されたトランザクションのクリア
リストとのやり取りのどの時点でも、clear
メソッドを使用して、トランザクション ログをクリアできます。
<button igxButton="contained" (click)="onClear()" [disabled]="this.getTransactionLog().length === 0">Clear Transactions</button>
public onClear(): void {
this.transactions.clear();
}