Merge pull request #4717 from MaximilianKrambach/sortTreeMulti

Drag/Drop multiselect
This commit is contained in:
Maximilian Krambach 2019-05-27 17:26:03 +02:00 committed by GitHub
commit b2c2d78c79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 94 additions and 5 deletions

View File

@ -2,18 +2,29 @@
<div class="line" *ngIf="!array.length"> <div class="line" *ngIf="!array.length">
<span translate>No data</span> <span translate>No data</span>
</div> </div>
<div class="line" *ngFor="let item of array; let i = index" cdkDrag> <div
<div class="section-one backgroundColorLight" cdkDragHandle *ngIf="enable"> [ngClass]="isSelectedRow(i) ? 'backgroundColorSelected line' : 'backgroundColorLight line'"
*ngFor="let item of array; let i = index"
cdkDrag
(click)="onItemClick($event, i)"
(cdkDragStarted)="dragStarted(i)"
>
<div class="section-one " cdkDragHandle *ngIf="enable">
<mat-icon>drag_indicator</mat-icon> <mat-icon>drag_indicator</mat-icon>
</div> </div>
<div class="section-two backgroundColorLight"> <div class="section-two">
<!-- {number}. {item.getTitle()} --> <!-- {number}. {item.getTitle()} -->
<span *ngIf="count">{{ i + 1 }}.&nbsp;</span> <span *ngIf="count">{{ i + 1 }}.&nbsp;</span>
<span>{{ item.getTitle() }}</span> <span>{{ item.getTitle() }}</span>
</div> </div>
<div class="section-three backgroundColorLight"> <div class="section-three">
<!-- Extra controls slot using implicit template references --> <!-- Extra controls slot using implicit template references -->
<ng-template [ngTemplateOutlet]="templateRef" [ngTemplateOutletContext]="{ $implicit: item }"></ng-template> <ng-template [ngTemplateOutlet]="templateRef" [ngTemplateOutletContext]="{ $implicit: item }"></ng-template>
</div> </div>
<div class="line" *cdkDragPreview>
<div class="spacer.left-10" *ngIf="multiSelectedIndex.length > 0">
{{ multiSelectedIndex.length }}&nbsp;<span translate>items selected</span>
</div>
</div>
</div> </div>
</div> </div>

View File

@ -36,6 +36,12 @@ export class SortingListComponent implements OnInit, OnDestroy {
*/ */
public array: Selectable[]; public array: Selectable[];
/**
* The index of multiple selected elements. Allows for multiple items to be
* selected and then moved
*/
public multiSelectedIndex: number[] = [];
/** /**
* Declare the templateRef to coexist between parent in child * Declare the templateRef to coexist between parent in child
*/ */
@ -143,12 +149,79 @@ export class SortingListComponent implements OnInit, OnDestroy {
} }
} }
/**
* Handles the start of a dragDrop event and clears multiSelect if the ittem dragged
* is not part of the selected items
*/
public dragStarted(index: number): void {
if (this.multiSelectedIndex.length && !this.multiSelectedIndex.includes(index)) {
this.multiSelectedIndex = [];
}
}
/** /**
* drop event * drop event
* @param event the event * @param event the event
*/ */
public drop(event: CdkDragDrop<Selectable[]>): void { public drop(event: CdkDragDrop<Selectable[]>): void {
moveItemInArray(this.array, event.previousIndex, event.currentIndex); if (this.multiSelectedIndex.length < 2) {
moveItemInArray(this.array, event.previousIndex, event.currentIndex);
} else {
const before: Selectable[] = [];
const insertions: Selectable[] = [];
const behind: Selectable[] = [];
for (let i = 0; i < this.array.length; i++) {
if (!this.multiSelectedIndex.includes(i)) {
if (i < event.currentIndex) {
before.push(this.array[i]);
} else if (i > event.currentIndex) {
behind.push(this.array[i]);
} else {
event.currentIndex < 1 ? behind.push(this.array[i]) : before.push(this.array[i]);
}
} else {
insertions.push(this.array[i]);
}
}
this.array = [...before, ...insertions, ...behind];
}
this.sortEvent.emit(this.array); this.sortEvent.emit(this.array);
this.multiSelectedIndex = [];
}
/**
* Handles a click on a row. If the control key is clicked, the element is
* added/removed from a multiselect list /(which will be handled on
* dropping)
*
* @param event MouseEvent.
* @param indx The index of the row clicked.
*/
public onItemClick(event: MouseEvent, indx: number): void {
if (event.ctrlKey) {
const ind = this.multiSelectedIndex.findIndex(i => i === indx);
if (ind === -1) {
this.multiSelectedIndex.push(indx);
} else {
this.multiSelectedIndex = this.multiSelectedIndex
.slice(0, ind)
.concat(this.multiSelectedIndex.slice(ind + 1));
}
} else {
// deselect all when clicking on an non-selected item
if (this.multiSelectedIndex.length && !this.multiSelectedIndex.includes(indx)) {
this.multiSelectedIndex = [];
}
}
}
/**
* Checks if the row at the given index is currently selected
*
* @param index
* @returns true if the item is currently selected
*/
public isSelectedRow(index: number): boolean {
return this.multiSelectedIndex.includes(index);
} }
} }

View File

@ -80,6 +80,11 @@
color: mat-color($accent, default-contrast) !important; color: mat-color($accent, default-contrast) !important;
} }
.backgroundColorSelected {
background-color: rgba(0, 0, 0, 0.155);
color: mat-color($foreground, text) !important;
}
.backgroundColorLight { .backgroundColorLight {
background-color: mat-color($background, hover); background-color: mat-color($background, hover);
color: mat-color($foreground, text) !important; color: mat-color($foreground, text) !important;