トランザクション サービスの使用方法

データソースの状態を保持し、一度に多くのトランザクションをコミットする必要があるコンポーネントを使用する場合、Transaction Service を利用できます。

Ignite UI for Angular グリッドコンポーネントの igxTransactionServiceigxHierarchicalTransactionService は、グリッドと統合して、追加設定なしに一括編集機能が使用できます。ただし、その他の Ignite UI for Angular またはカスタムコンポーネントでトランザクションを使用する必要がある場合は、再度 igxTransactionService を使用して、同様の動作を実装できます。

Angular トランザクション サービスの使用方法の例

このトピックでは、igxList コンポーネントを使用して、トランザクションを有効にする方法を示します。トランザクションを追加する方法、pipe を介してデータを変換する方法、およびコミットされようとしている変更をユーザーに表示するするためにビューを視覚的に更新する方法を示します。

このサンプルが気に入りましたか? 完全な Angular ツールキットにアクセスして、すばやく独自のアプリの作成を開始します。無料でダウンロードできます。

トランザクション サービスを含む

トランザクション サービスをプロジェクトに含む

アプリケーションに 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 ファイルは、アプリケーションで必要となる igxTransactionServiceigniteui-angular ライブラリからインポートし、State および Transaction インターフェイスと TransactionType enum をインポートする必要があります。

import { IgxTransactionService, State, Transaction, TransactionType } from "igniteui-angular";

次にトランザクション サービスをコンストラクターにインポートします。

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

igxList の定義

html テンプレートで igxList コンポーネントに editdelete、および 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>

保留されたトランザクションをコミット

すべての変更が完了したら、igxTransactionServicecommit メソッドを使用して、一度にすべてをコミットできます。指定されたデータにすべてのトランザクションを適用します。

<button igxButton="raised" (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="raised" (click)="onClear()" [disabled]="this.getTransactionLog().length === 0">Clear Transactions</button>
public onClear(): void {
    this.transactions.clear();
}

その他のリソース