angular2-data-table
Version:
angular2-data-table is a Angular2 component for presenting large and complex data.
102 lines (79 loc) • 2.62 kB
text/typescript
import {
Directive, Output, EventEmitter, ContentChildren,
QueryList, KeyValueDiffers, AfterContentInit, OnDestroy
} from '@angular/core';
import { DraggableDirective } from './draggable.directive';
export class OrderableDirective implements AfterContentInit, OnDestroy {
reorder: EventEmitter<any> = new EventEmitter();
draggables: QueryList<DraggableDirective>;
positions: any;
differ: any;
constructor(differs: KeyValueDiffers) {
this.differ = differs.find({}).create(null);
}
ngAfterContentInit(): void {
// HACK: Investigate Better Way
this.updateSubscriptions();
this.draggables.changes.subscribe(
this.updateSubscriptions.bind(this));
}
ngOnDestroy(): void {
this.draggables.forEach(d => {
d.dragStart.unsubscribe();
d.dragEnd.unsubscribe();
});
}
updateSubscriptions(): void {
const diffs = this.differ.diff(this.draggables.toArray());
if(diffs) {
const subscribe = ({ currentValue, previousValue }: any) => {
unsubscribe({ previousValue });
if(currentValue) {
currentValue.dragStart.subscribe(this.onDragStart.bind(this));
currentValue.dragEnd.subscribe(this.onDragEnd.bind(this));
}
};
const unsubscribe = ({ previousValue }: any) => {
if(previousValue) {
previousValue.dragStart.unsubscribe();
previousValue.dragEnd.unsubscribe();
}
};
diffs.forEachAddedItem(subscribe.bind(this));
diffs.forEachChangedItem(subscribe.bind(this));
diffs.forEachRemovedItem(unsubscribe.bind(this));
}
}
onDragStart(): void {
this.positions = {};
let i = 0;
for(let dragger of this.draggables.toArray()) {
let elm = dragger.element;
this.positions[dragger.dragModel.prop] = {
left: parseInt(elm.offsetLeft.toString(), 0),
index: i++
};
}
}
onDragEnd({ element, model }: any) {
const newPos = parseInt(element.offsetLeft.toString(), 0);
const prevPos = this.positions[model.prop];
let i = 0;
for(let prop in this.positions) {
let pos = this.positions[prop];
let movedLeft = newPos < pos.left && prevPos.left > pos.left;
let movedRight = newPos > pos.left && prevPos.left < pos.left;
if(movedLeft || movedRight) {
this.reorder.emit({
prevIndex: prevPos.index,
newIndex: i,
model
});
}
i++;
}
element.style.left = 'auto';
}
}