UNPKG

ng-ytl-zorro-antd

Version:

An enterprise-class UI components based on Ant Design and Angular

239 lines (206 loc) 8.26 kB
// tslint:disable:member-ordering import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ElementRef, EventEmitter, Input, OnChanges, Output, SimpleChanges, TemplateRef, ViewEncapsulation } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import { of } from 'rxjs/observable/of'; import { NzLocaleService } from '../locale/index'; import { toBoolean } from '../util/convert'; import { TransferItem } from './item'; export interface TransferCanMove { direction: string; list: TransferItem[]; } export interface TransferChange { from: string; to: string; list: TransferItem[]; } export interface TransferSearchChange { direction: string; value: string; } export interface TransferSelectChange { direction: string; checked: boolean; list: TransferItem[]; item: TransferItem; } @Component({ selector: 'nz-transfer', template: ` <nz-transfer-list class="ant-transfer-list" [ngStyle]="nzListStyle" data-direction="left" [titleText]="nzTitles[0]" [dataSource]="leftDataSource" [filter]="leftFilter" [filterOption]="nzFilterOption" (filterChange)="handleFilterChange($event)" [render]="render" [showSearch]="nzShowSearch" [searchPlaceholder]="nzSearchPlaceholder" [notFoundContent]="nzNotFoundContent" [itemUnit]="nzItemUnit" [itemsUnit]="nzItemsUnit" [footer]="footer" (handleSelect)="handleLeftSelect($event)" (handleSelectAll)="handleLeftSelectAll($event)"></nz-transfer-list> <div class="ant-transfer-operation"> <button nz-button (click)="moveToLeft()" [disabled]="!leftActive" [nzType]="'primary'" [nzSize]="'small'"> <i class="anticon anticon-left"></i><span *ngIf="nzOperations[1]">{{ nzOperations[1] }}</span> </button> <button nz-button (click)="moveToRight()" [disabled]="!rightActive" [nzType]="'primary'" [nzSize]="'small'"> <i class="anticon anticon-right"></i><span *ngIf="nzOperations[0]">{{ nzOperations[0] }}</span> </button> </div> <nz-transfer-list class="ant-transfer-list" [ngStyle]="nzListStyle" data-direction="right" [titleText]="nzTitles[1]" [dataSource]="rightDataSource" [filter]="rightFilter" [filterOption]="nzFilterOption" (filterChange)="handleFilterChange($event)" [render]="render" [showSearch]="nzShowSearch" [searchPlaceholder]="nzSearchPlaceholder" [notFoundContent]="nzNotFoundContent" [itemUnit]="nzItemUnit" [itemsUnit]="nzItemsUnit" [footer]="footer" (handleSelect)="handleRightSelect($event)" (handleSelectAll)="handleRightSelectAll($event)"></nz-transfer-list> `, encapsulation: ViewEncapsulation.None, styleUrls: [ './style/index.less', './style/patch.less' ], // tslint:disable-next-line:use-host-property-decorator host: { '[class.ant-transfer]': 'true' }, changeDetection: ChangeDetectionStrategy.OnPush }) export class NzTransferComponent implements OnChanges { private _showSearch = false; leftFilter = ''; rightFilter = ''; // region: fields @Input() nzDataSource: TransferItem[] = []; @Input() nzTitles: string[] = this._locale.translate('Transfer.titles').split(','); @Input() nzOperations: string[] = []; @Input() nzListStyle: object; @Input() nzItemUnit = this._locale.translate('Transfer.itemUnit'); @Input() nzItemsUnit = this._locale.translate('Transfer.itemsUnit'); @Input() canMove: (arg: TransferCanMove) => Observable<TransferItem[]> = (arg: TransferCanMove) => of(arg.list); @ContentChild('render') render: TemplateRef<void>; @ContentChild('footer') footer: TemplateRef<void>; // search @Input() set nzShowSearch(value: boolean) { this._showSearch = toBoolean(value); } get nzShowSearch(): boolean { return this._showSearch; } @Input() nzFilterOption: (inputValue: string, item: TransferItem) => boolean; @Input() nzSearchPlaceholder = this._locale.translate('Transfer.searchPlaceholder'); @Input() nzNotFoundContent = this._locale.translate('Transfer.notFoundContent'); // events @Output() nzChange: EventEmitter<TransferChange> = new EventEmitter(); @Output() nzSearchChange: EventEmitter<TransferSearchChange> = new EventEmitter(); @Output() nzSelectChange: EventEmitter<TransferSelectChange> = new EventEmitter(); // endregion // region: process data // left leftDataSource: TransferItem[] = []; // right rightDataSource: TransferItem[] = []; private splitDataSource(): void { this.leftDataSource = []; this.rightDataSource = []; this.nzDataSource.forEach(record => { if (record.direction === 'right') { this.rightDataSource.push(record); } else { this.leftDataSource.push(record); } }); } private getCheckedData(direction: string): TransferItem[] { return this[direction === 'left' ? 'leftDataSource' : 'rightDataSource'].filter(w => w.checked); } handleLeftSelectAll = (checked: boolean) => this.handleSelect('left', checked); handleRightSelectAll = (checked: boolean) => this.handleSelect('right', checked); handleLeftSelect = (item: TransferItem) => this.handleSelect('left', item.checked, item); handleRightSelect = (item: TransferItem) => this.handleSelect('right', item.checked, item); handleSelect(direction: 'left' | 'right', checked: boolean, item?: TransferItem): void { const list = this.getCheckedData(direction); this.updateOperationStatus(direction, list.length); this.nzSelectChange.emit({ direction, checked, list, item }); } handleFilterChange(ret: { direction: string, value: string }): void { this.nzSearchChange.emit(ret); this.cd.detectChanges(); } // endregion // region: operation leftActive = false; rightActive = false; private updateOperationStatus(direction: string, count?: number): void { this[direction === 'right' ? 'leftActive' : 'rightActive'] = (typeof count === 'undefined' ? this.getCheckedData(direction).filter(w => !w.disabled).length : count) > 0; this.cd.detectChanges(); } moveToLeft = () => this.moveTo('left'); moveToRight = () => this.moveTo('right'); moveTo(direction: string): void { const oppositeDirection = direction === 'left' ? 'right' : 'left'; this.updateOperationStatus(oppositeDirection, 0); const datasource = direction === 'left' ? this.rightDataSource : this.leftDataSource; const moveList = datasource.filter(item => item.checked === true && !item.disabled); this.canMove({ direction, list: moveList }) .subscribe( newMoveList => this.truthMoveTo(direction, newMoveList.filter(i => !!i)), () => moveList.forEach(i => i.checked = false) ); } private truthMoveTo(direction: string, list: TransferItem[]): void { const oppositeDirection = direction === 'left' ? 'right' : 'left'; const datasource = direction === 'left' ? this.rightDataSource : this.leftDataSource; const targetDatasource = direction === 'left' ? this.leftDataSource : this.rightDataSource; for (const item of list) { const idx = datasource.indexOf(item); if (idx === -1) continue; item.checked = false; targetDatasource.push(item); datasource.splice(idx, 1); } this.updateOperationStatus(oppositeDirection); this.nzChange.emit({ from: oppositeDirection, to: direction, list }); // this.nzSelectChange.emit({ direction: oppositeDirection, list: [] }); } // endregion constructor(private _locale: NzLocaleService, private el: ElementRef, private cd: ChangeDetectorRef) { } ngOnChanges(changes: SimpleChanges): void { if ('nzDataSource' in changes || 'nzTargetKeys' in changes) { this.splitDataSource(); this.updateOperationStatus('left'); this.updateOperationStatus('right'); } this.cd.detectChanges(); } }