import { Component, OnInit, Input, Directive, TemplateRef, ContentChild, ElementRef, HostBinding, AfterViewInit, ViewEncapsulation, Output, EventEmitter, ChangeDetectionStrategy, SimpleChanges, OnChanges, ViewChild } from '@angular/core'; import { FarrisDataItem } from '@farris/ui-common'; import { DataListFacadeService } from './core/datalist-facade.service'; import { SelectItem } from './core/types'; @Directive({ selector: '[list-item-tmp]' }) export class DataListItemTemplateDirective { constructor(public template: TemplateRef) {} } @Component({ selector: 'farris-datalist', templateUrl: './datalist.component.html', styles: [ ` .ps__rail-x, .ps__rail-y { z-index: 9; } .norecords-content { height: 8.125rem; padding: 7.8125rem 0 0; width: 100%; text-align: center; font-size: 1rem; color: rgba(0,0,0,.25); background: url(imgs/table-norecords.png) top center no-repeat; margin: -4.0625rem 0 0 -.625rem; line-height: 2.5rem; } ` ], providers: [DataListFacadeService], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush }) export class DatalistComponent implements OnInit, OnChanges, AfterViewInit { @HostBinding('class.f-datalist') cls = true; @HostBinding('class.farris-main-area') get fluid() { return this._height === 'auto' ? false : this.fit; } @Input() itemHeight: number; @Input() title: string; @Input() data: any; @Input() textField: string; @Input() valueField: string; @Input() idField: string; @Input() fit = true; @Input() width = 300; @Input() height: number | string = 400; @Input() multiSelect = false; @Input() disabled = false; @Input() showHeader = false; @Input() showCheckBox = false; @Input() headerHeight = 40; @Input() selectedValues: string; @Input() enableCancelSelected = true; /** 分隔符,默认为 , */ @Input() separator = ','; @ContentChild(DataListItemTemplateDirective, { read: TemplateRef }) itemTemplate: TemplateRef; @Output() selected = new EventEmitter(); @Output() unSelected = new EventEmitter(); @Output() selectedValuesChange = new EventEmitter(); scrollbarHeight$ = this.store.containerHeight$; // tslint:disable-next-line:variable-name _options$ = this.store.options$; data$ = this.store.data$; private _height: any; constructor(public el: ElementRef, public store: DataListFacadeService) {} ngOnChanges(changes: SimpleChanges): void { if (changes && changes.data && !changes.data.isFirstChange()) { this.initCtrlState(); } if (changes.selectedValues && !changes.selectedValues.isFirstChange()) { if (this.selectedValues !== '' && this.selectedValues !== undefined && this.selectedValues !== null) { this.store.setSelections(this.selectedValues, this.separator); } else { this.clearSelections(); } } } ngOnInit() { this._height = this.height; this.initCtrlState(); } ngAfterViewInit() { setTimeout(() => { if (this.selectedValues && this.height !== 'auto') { let val = this.selectedValues; if (this.selectedValues.indexOf(this.separator) > -1) { val = this.selectedValues.indexOf(this.separator)[0]; } const index = this.data.findIndex(n => n[this.idField] == val); const ulEl = this.el.nativeElement.querySelector('ul.list-group'); if (ulEl.children[index]) { ulEl.children[index].scrollIntoView({block: 'nearest'}); } } }, 10); } private loadData() { if (this.data) { this.store.loadData(this.data, this.selectedValues, this.separator); } } private initCtrlState() { const { title, textField, fit, idField, valueField, width, height, multiSelect, disabled, headerHeight, separator } = { ...this }; this.store.initState({ title, textField, valueField, fit, idField, width, height, multiSelect, disabled, headerHeight, separator }); this.loadData(); } clearSelections() { this.store.clearSelections(); } resize() { if (this.fit) { const container = this.el.nativeElement.parentElement; const width = container.offsetWidth; const height = container.offsetHeight; this.store.updateContainerSize(width, height); } } private updateSelectValues() { const values = this.store.getSelections().map(item => { return item[this.valueField]; }); this.selectedValues = values.join(this.separator); this.selectedValuesChange.emit(this.selectedValues); } onSelectHandler(event: Event, index: number, item: FarrisDataItem) { event.stopPropagation(); if (this.disabled) { return false; } const { data } = { ...item }; if (!this.store.isSelect(item.id)) { this.store.selectItem(data, index); this.updateSelectValues(); this.selected.emit({ index, data }); } else { if (this.enableCancelSelected) { this.store.unSelectItem(data); this.updateSelectValues(); this.unSelected.emit({ index, data }); } } } onCheckedChange($event) { const { index, row, originalEvent } = $event; this.onSelectHandler(originalEvent, index, row); } isChecked(item: FarrisDataItem) { let val = this.selectedValues; if (this.selectedValues === null && this.selectedValues === undefined) { val = ''; } if (typeof val === 'boolean') { val = '' + val; } if (val) { let _vals = []; if (this.multiSelect) { _vals = val.split(this.separator); } else { _vals = [val]; } return _vals.some( v => v == '' + item.data[this.valueField]); } return false; } isSelected(item: FarrisDataItem) { return this.isChecked(item); } selectAll() { this.selectedValues = this.data.map(item => item[this.valueField]).join(this.separator); this.store.selectAll(); } unSelectAll() { this.selectedValues = ''; this.store.clearSelections(); } } @Directive({ // tslint:disable-next-line:directive-selector selector: '[farrist-datalist-item]' }) export class DataListItemComponentDirective implements OnInit { @Input('farrist-datalist-item') data: FarrisDataItem; constructor(private el: ElementRef) {} ngOnInit() {} } /** * 表体checkbox 组件 */ @Component({ // tslint:disable-next-line:component-selector selector: 'dl-checkbox', template: `
`, styles: [ ` :host .custom-checkbox { opacity: 1; float: none; margin: 0; vertical-align: top; padding-right: 0px; } ` ] }) export class DataListCheckboxComponent implements OnInit { @Input() checked: boolean; @Input() disabled: boolean; @Input() index: number; @Input() row: any; @Output() checkedChange = new EventEmitter(); @ViewChild('chk') chk: ElementRef; constructor() {} ngOnInit() {} handleClick(event) { this.checked = !this.checked; this.checkedChange.emit({ originalEvent: event, index: this.index, row: this.row, state: this.checked }); event.stopPropagation(); } }