거래 서비스 이용 방법

    데이터 소스의 상태를 보존하고 한 번에 많은 트랜잭션을 커밋해야 하는 구성 요소를 사용할 때 Transaction Service 활용할 수 있습니다.

    Ignite UI for Angular로 작업할 때 그리드와 통합되어 즉시 일괄 편집을 제공하는 igxTransactionServiceigxHierarchicalTransactionService 사용할 수 있습니다. 그러나 Ignite UI for Angular 또는 사용자 정의 구성 요소와 트랜잭션을 사용해야 하는 경우 igxTransactionService 다시 사용하고 유사한 동작을 구현할 수 있습니다.

    Angular How to use the Transaction service Example

    이 주제에서는 igxList 구성 요소를 사용하여 트랜잭션을 활성화하는 방법을 보여줍니다. 트랜잭션을 추가하는 방법, 파이프를 통해 데이터를 변환하는 방법, 커밋될 변경 사항을 사용자가 볼 수 있도록 뷰를 시각적으로 업데이트하는 방법을 보여줍니다.

    Include Transaction Service

    Include Transaction Service in project

    애플리케이션에 IgxTransactionService 포함하는 두 가지 옵션이 있습니다. 첫 번째는 위의 데모에서 수행된 것처럼 AppModule 또는 애플리케이션의 다른 상위 모듈에 추가하는 것입니다.

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

    다른 옵션은 트랜잭션 서비스가 사용되는 구성 요소에 이를 제공하는 것입니다.

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

    Inject Transaction Service in component

    우리의 ts 파일을 가져와야 합니다. igxTransactionService ~로부터 igniteui-angular 도서관은 물론이고 State 그리고 Transaction 인터페이스와 TransactionType 우리의 애플리케이션에 필요한 열거형:

    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>) { ... }
    

    Define igxList

    HTML 템플릿에서 우리는 igxList 구성 요소 편집하다, 삭제 그리고 추가하다 목록과 해당 항목을 수정하는 작업:

    <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

    위의 목록 구성 요소는 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;
        }
    }
    

    Edit, delete, add functionality

    Define edit functionality

    두 번째 목록 항목에는 항목의 데이터를 업데이트하는 편집 버튼이 포함되어 있습니다.

    <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;
    }
    

    Define delete functionality

    세 번째 목록 항목에는 항목의 데이터를 삭제하는 삭제 버튼이 포함되어 있습니다.

    <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;
    }
    

    Define add functionality

    목록 끝에 새 항목을 목록에 추가하는 ADD 버튼이 추가됩니다.

    <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;
    }
    

    Transaction 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);
        });
    }
    

    또한 목록의 현재 상태에 대한 표현을 추가할 것입니다. 보류 중인 트랜잭션이 커밋되기 전에 데이터가 어떻게 보이는지 보여줍니다.

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

    Commit pending transactions

    모든 변경 사항이 완료되면 igxTransactionServicecommit 메소드를 사용하여 한 번에 모두 커밋할 수 있습니다. 제공된 데이터에 대한 모든 트랜잭션을 적용합니다.

    <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 pending transactions

    목록과 상호 작용하는 어느 시점에서든 clear 메소드를 사용하여 트랜잭션 로그를 지울 수 있습니다.

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

    Additional Resources