ng-ytl-zorro-antd
Version:
An enterprise-class UI components based on Ant Design and Angular
239 lines (206 loc) • 8.26 kB
text/typescript
// 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;
}
export class NzTransferComponent implements OnChanges {
private _showSearch = false;
leftFilter = '';
rightFilter = '';
// region: fields
nzDataSource: TransferItem[] = [];
nzTitles: string[] = this._locale.translate('Transfer.titles').split(',');
nzOperations: string[] = [];
nzListStyle: object;
nzItemUnit = this._locale.translate('Transfer.itemUnit');
nzItemsUnit = this._locale.translate('Transfer.itemsUnit');
canMove: (arg: TransferCanMove) => Observable<TransferItem[]> = (arg: TransferCanMove) => of(arg.list);
render: TemplateRef<void>;
footer: TemplateRef<void>;
// search
set nzShowSearch(value: boolean) {
this._showSearch = toBoolean(value);
}
get nzShowSearch(): boolean {
return this._showSearch;
}
nzFilterOption: (inputValue: string, item: TransferItem) => boolean;
nzSearchPlaceholder = this._locale.translate('Transfer.searchPlaceholder');
nzNotFoundContent = this._locale.translate('Transfer.notFoundContent');
// events
nzChange: EventEmitter<TransferChange> = new EventEmitter();
nzSearchChange: EventEmitter<TransferSearchChange> = new EventEmitter();
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();
}
}