-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(sortable): module #1295
Merged
Merged
feat(sortable): module #1295
Changes from 2 commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
eddede5
Added sortable-list module
Le0Michine 75b634f
added sortable-list module into the main module
Le0Michine 0dca2b1
renamed sortable-list to sortable
Le0Michine b20bb27
removed sortable module from root index.ts
Le0Michine 5a6553b
inlined html template
Le0Michine 6d08383
created docs page for sortable component
Le0Michine 556d97b
removed console.log
Le0Michine 9db1056
added tests for reordering
Le0Michine 7eb8e4e
added tests for onZoneDragover method
Le0Michine 2edce40
added test for insert item from another container
Le0Michine 65f479f
fixed quotes
Le0Michine 40377ff
fixed insertion test
Le0Michine 0287049
finished component covering
Le0Michine ca95219
Merge remote-tracking branch 'upstream/development' into development
Le0Michine 2dfd04f
Merge remote-tracking branch 'upstream/development' into development
Le0Michine 92ea666
Merge branch 'development' of https://github.com/Le0Michine/ng2-boots…
Le0Michine b1abbdf
changed dirs structure
Le0Michine 3d37cee
use dumb object instead of Event
Le0Michine 5b8ed5a
Merge remote-tracking branch 'upstream/development' into development
Le0Michine 6efb630
updated docs
Le0Michine c469581
update docs (added doc comments)
Le0Michine cae3a62
fixed compatibility with firefox
Le0Michine File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './sortable-list.component'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<div | ||
[ngClass]="wrapperClass" | ||
[ngStyle]="wrapperStyle" | ||
[ngStyle]="wrapperStyle" | ||
(dragover)="onZoneDragover($event)" | ||
(drop)="resetActiveItem()" | ||
(mouseleave)="resetActiveItem()" | ||
> | ||
<div | ||
*ngIf="showPlaceholder" | ||
[ngClass]="placeholderClass" | ||
[ngStyle]="placeholderStyle" | ||
(dragover)="onItemDragover($event, 0)" | ||
>{{placeholderItem}}</div> | ||
<div | ||
[@flyInOut]="'in'" | ||
(@flyInOut.done)="updatePlaceholderState()" | ||
(@flyInOut.start)="showPlaceholder = false" | ||
*ngFor="let item of items; let i=index;" | ||
[ngClass]="[ itemClass, i === activeItem ? itemActiveClass : '' ]" | ||
[ngStyle]="getItemStyle(i === activeItem)" | ||
draggable="true" | ||
(dragstart)="onItemDragstart($event, item, i)" | ||
(dragend)="resetActiveItem()" | ||
(dragover)="onItemDragover($event, i)" | ||
>{{item.value}}</div> | ||
</div> |
167 changes: 167 additions & 0 deletions
167
src/sortable-list/components/sortable-list.component.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
import { Component, Input, Output, EventEmitter, forwardRef, animate, style, state, transition, keyframes, trigger } from '@angular/core'; | ||
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms'; | ||
import 'rxjs/add/operator/first'; | ||
|
||
import { DraggableItem } from '../models'; | ||
import { DraggableItemService } from '../services'; | ||
|
||
const nullCallback = (arg?: any): void => { return void 0; }; | ||
|
||
/* tslint:disable */ | ||
@Component({ | ||
selector: 'ng2-sortable-list', | ||
templateUrl: './sortable-list.component.html', | ||
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong. |
||
providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SortableComponent), multi: true }], | ||
animations: [ | ||
trigger('flyInOut', [ | ||
state('in', style({ height: '*', width: '*' })), | ||
transition('void => *', [ | ||
style({ height: 0, width: 0 }), | ||
animate('100ms ease-out') | ||
]), | ||
transition('* => void', [ | ||
style({ height: '*', width: '*' }), | ||
animate('100ms ease-out', style({ height: 0, width: 0 })) | ||
]) | ||
]) | ||
] | ||
}) | ||
/* tslint:enable */ | ||
export class SortableComponent implements ControlValueAccessor { | ||
private static globalZoneIndex: number = 0; | ||
|
||
@Input() public fieldName: string; | ||
@Input() public wrapperClass: string = ''; | ||
@Input() public wrapperStyle: {} = {}; | ||
@Input() public itemClass: string = ''; | ||
@Input() public itemStyle: {} = {}; | ||
@Input() public itemActiveClass: string = ''; | ||
@Input() public itemActiveStyle: {} = {}; | ||
@Input() public placeholderClass: string = ''; | ||
@Input() public placeholderStyle: {} = {}; | ||
@Input() public placeholderItem: string = ''; | ||
|
||
@Output() public onChange: EventEmitter<any[]> = new EventEmitter<any[]>(); | ||
|
||
private _items: SortableItem[]; | ||
|
||
private showPlaceholder: boolean = false; | ||
|
||
private get items(): SortableItem[] { | ||
return this._items; | ||
} | ||
|
||
private set items(value: SortableItem[]) { | ||
this._items = value; | ||
let out = this.items.map((x: SortableItem) => x.initData); | ||
this.onChanged(out); | ||
this.onChange.emit(out); | ||
} | ||
|
||
private onTouched: () => void = nullCallback; | ||
private onChanged: (_: any) => void = nullCallback; | ||
|
||
private transfer: DraggableItemService; | ||
private currentZoneIndex: number; | ||
private activeItem: number = -1; | ||
|
||
public constructor(transfer: DraggableItemService) { | ||
this.transfer = transfer; | ||
this.currentZoneIndex = SortableComponent.globalZoneIndex++; | ||
this.transfer.onCaptureItem().subscribe((item: DraggableItem) => this.onDrop(item)); | ||
} | ||
|
||
public onItemDragstart(event: DragEvent, item: SortableItem, i: number): void { | ||
this.onTouched(); | ||
this.transfer.dragStart({ | ||
event, | ||
item, | ||
i, | ||
initialIndex: i, | ||
lastZoneIndex: this.currentZoneIndex, | ||
overZoneIndex: this.currentZoneIndex | ||
}); | ||
} | ||
|
||
public onItemDragover(event: DragEvent, i: number): void { | ||
if (!this.transfer.getItem()) { | ||
return; | ||
} | ||
event.preventDefault(); | ||
let dragItem = this.transfer.captureItem(this.currentZoneIndex, this.items.length); | ||
let newArray: any[] = []; | ||
if (!this.items.length) { | ||
newArray = [ dragItem.item ]; | ||
} else if (dragItem.i > i) { | ||
newArray = [ | ||
...this.items.slice(0, i), | ||
dragItem.item, | ||
...this.items.slice(i, dragItem.i), | ||
...this.items.slice(dragItem.i + 1) | ||
]; | ||
} else { // this.draggedItem.i < i | ||
newArray = [ | ||
...this.items.slice(0, dragItem.i), | ||
...this.items.slice(dragItem.i + 1, i + 1), | ||
dragItem.item, | ||
...this.items.slice(i + 1) | ||
]; | ||
} | ||
this.items = newArray; | ||
dragItem.i = i; | ||
this.activeItem = i; | ||
} | ||
|
||
public onZoneDragover(event: DragEvent): void { | ||
if (!this.transfer.getItem()) { | ||
return; | ||
} | ||
event.preventDefault(); | ||
} | ||
|
||
public onDrop(item: DraggableItem): void { | ||
if (item && | ||
item.overZoneIndex !== this.currentZoneIndex && | ||
item.lastZoneIndex === this.currentZoneIndex | ||
) { | ||
this.items = this.items.filter((x: SortableItem, i: number) => i !== item.i); | ||
} | ||
this.resetActiveItem(); | ||
} | ||
|
||
public resetActiveItem(): void { | ||
this.activeItem = -1; | ||
} | ||
|
||
public registerOnChange(callback: (_: any) => void): void { | ||
this.onChanged = callback; | ||
} | ||
|
||
public registerOnTouched(callback: () => void): void { | ||
this.onTouched = callback; | ||
} | ||
|
||
public writeValue(value: any[]): void { | ||
if (value) { | ||
this.items = value.map((x: any, i: number) => ({ id: i, initData: x, value: this.fieldName ? x[this.fieldName] : x })); | ||
console.log('items', this.items); | ||
} else { | ||
this.items = []; | ||
} | ||
this.updatePlaceholderState(); | ||
} | ||
|
||
public updatePlaceholderState(): void { | ||
this.showPlaceholder = !this._items.length; | ||
} | ||
|
||
public getItemStyle(isActive: boolean): {} { | ||
return isActive ? Object.assign({}, this.itemStyle, this.itemActiveStyle) : this.itemStyle; | ||
} | ||
} | ||
|
||
export declare interface SortableItem { | ||
id: number; | ||
value: string; | ||
initData: any; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './sortable-list.module'; | ||
This comment was marked as off-topic.
Sorry, something went wrong. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
export interface DraggableItem { | ||
event: DragEvent; | ||
item: any; | ||
i: number; | ||
initialIndex: number; | ||
lastZoneIndex: number; | ||
overZoneIndex: number; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './draggable-item'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { Injectable } from '@angular/core'; | ||
import { Observable } from 'rxjs/Observable'; | ||
import { Subject } from 'rxjs/Subject'; | ||
import { DraggableItem } from '../models'; | ||
|
||
@Injectable() | ||
export class DraggableItemService { | ||
private draggableItem: DraggableItem; | ||
|
||
private onCapture: Subject<DraggableItem> = new Subject(); | ||
|
||
public dragStart(item: DraggableItem): void { | ||
this.draggableItem = item; | ||
} | ||
|
||
public getItem(): DraggableItem { | ||
return this.draggableItem; | ||
} | ||
|
||
public captureItem(overZoneIndex: number, newIndex: number): DraggableItem { | ||
if (this.draggableItem.overZoneIndex !== overZoneIndex) { | ||
this.draggableItem.lastZoneIndex = this.draggableItem.overZoneIndex; | ||
this.draggableItem.overZoneIndex = overZoneIndex; | ||
this.onCapture.next(this.draggableItem); | ||
this.draggableItem = Object.assign( | ||
{}, | ||
this.draggableItem, | ||
{ overZoneIndex, i: newIndex } | ||
); | ||
} | ||
return this.draggableItem; | ||
} | ||
|
||
public onCaptureItem(): Observable<DraggableItem> { | ||
return this.onCapture; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './draggable-item.service'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { NgModule } from '@angular/core'; | ||
import { BrowserModule } from '@angular/platform-browser'; | ||
|
||
import { SortableComponent } from './components'; | ||
import { DraggableItemService } from './services'; | ||
|
||
@NgModule({ | ||
declarations: [ | ||
SortableComponent | ||
], | ||
imports: [ | ||
BrowserModule | ||
], | ||
exports: [ | ||
BrowserModule, | ||
SortableComponent | ||
], | ||
providers: [ | ||
DraggableItemService | ||
] | ||
}) | ||
export class SortableListModule { } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.