From 0fe58a9c044fd4d9b7fc76f6fb61f7d87b5e9ddf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1?= Date: Tue, 12 Oct 2021 16:15:46 +0200 Subject: [PATCH 1/3] feat: (draghandle) drag handle implementation --- .../drag-handle/drag-handle.component.css | 30 ++++++++++++++++++ .../drag-handle/drag-handle.component.html | 19 +++++++++++ .../drag-handle/drag-handle.component.ts | 12 +++++++ .../introduction/introduction.component.html | 6 ++++ .../app/introduction/introduction.module.ts | 4 ++- projects/ng-sortgrid-demo/src/assets/gs7.png | Bin 0 -> 25559 bytes .../lib/ngsg-drag-handle.directive.spec.ts | 17 ++++++++++ .../src/lib/ngsg-drag-handle.directive.ts | 9 ++++++ .../src/lib/ngsg-item.directive.ts | 15 ++++++++- projects/ng-sortgrid/src/lib/ngsg.module.ts | 5 +-- 10 files changed, 113 insertions(+), 4 deletions(-) create mode 100644 projects/ng-sortgrid-demo/src/app/introduction/examples/drag-handle/drag-handle.component.css create mode 100644 projects/ng-sortgrid-demo/src/app/introduction/examples/drag-handle/drag-handle.component.html create mode 100644 projects/ng-sortgrid-demo/src/app/introduction/examples/drag-handle/drag-handle.component.ts create mode 100644 projects/ng-sortgrid-demo/src/assets/gs7.png create mode 100644 projects/ng-sortgrid/src/lib/ngsg-drag-handle.directive.spec.ts create mode 100644 projects/ng-sortgrid/src/lib/ngsg-drag-handle.directive.ts diff --git a/projects/ng-sortgrid-demo/src/app/introduction/examples/drag-handle/drag-handle.component.css b/projects/ng-sortgrid-demo/src/app/introduction/examples/drag-handle/drag-handle.component.css new file mode 100644 index 0000000..be5f0a6 --- /dev/null +++ b/projects/ng-sortgrid-demo/src/app/introduction/examples/drag-handle/drag-handle.component.css @@ -0,0 +1,30 @@ +.example-box { + width: 200px; + height: 200px; + padding: 10px; + box-sizing: border-box; + border: solid 1px #ccc; + color: rgba(0, 0, 0, 0.87); + display: flex; + justify-content: center; + align-items: center; + text-align: center; + background: #fff; + border-radius: 4px; + position: relative; + z-index: 1; + transition: box-shadow 200ms cubic-bezier(0, 0, 0.2, 1); + box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), + 0 2px 2px 0 rgba(0, 0, 0, 0.14), + 0 1px 5px 0 rgba(0, 0, 0, 0.12); +} + +.example-handle { + position: absolute; + top: 10px; + right: 10px; + color: #ccc; + cursor: move; + width: 24px; + height: 24px; +} diff --git a/projects/ng-sortgrid-demo/src/app/introduction/examples/drag-handle/drag-handle.component.html b/projects/ng-sortgrid-demo/src/app/introduction/examples/drag-handle/drag-handle.component.html new file mode 100644 index 0000000..7aa2dd7 --- /dev/null +++ b/projects/ng-sortgrid-demo/src/app/introduction/examples/drag-handle/drag-handle.component.html @@ -0,0 +1,19 @@ +
1. Drag the items around using handle
+ +
+
+ +

+ {{ item }} +

+ +
+ + + + +
+
diff --git a/projects/ng-sortgrid-demo/src/app/introduction/examples/drag-handle/drag-handle.component.ts b/projects/ng-sortgrid-demo/src/app/introduction/examples/drag-handle/drag-handle.component.ts new file mode 100644 index 0000000..b77b84f --- /dev/null +++ b/projects/ng-sortgrid-demo/src/app/introduction/examples/drag-handle/drag-handle.component.ts @@ -0,0 +1,12 @@ +import {Component} from '@angular/core'; + +@Component({ + selector: 'ngsg-demo-drag-handle', + templateUrl: 'drag-handle.component.html', + styleUrls: ['./drag-handle.component.css'] +}) +export class DragHandleComponent { + + public items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; +} + diff --git a/projects/ng-sortgrid-demo/src/app/introduction/introduction.component.html b/projects/ng-sortgrid-demo/src/app/introduction/introduction.component.html index d17adb4..0c89868 100644 --- a/projects/ng-sortgrid-demo/src/app/introduction/introduction.component.html +++ b/projects/ng-sortgrid-demo/src/app/introduction/introduction.component.html @@ -36,4 +36,10 @@

5. Scrolling

+
+ +

6. Customizing the drag area using a handle

+ + +
diff --git a/projects/ng-sortgrid-demo/src/app/introduction/introduction.module.ts b/projects/ng-sortgrid-demo/src/app/introduction/introduction.module.ts index b13d541..ada54ac 100644 --- a/projects/ng-sortgrid-demo/src/app/introduction/introduction.module.ts +++ b/projects/ng-sortgrid-demo/src/app/introduction/introduction.module.ts @@ -5,6 +5,7 @@ import {NgsgModule} from '../../../../ng-sortgrid/src/lib/ngsg.module'; import {SharedModule} from '../shared/shared.module'; import {AsyncPipeMemoryComponent} from './examples/async-pipe/async-pipe-memory.component'; +import { DragHandleComponent } from './examples/drag-handle/drag-handle.component'; import {GettingStartedMemoryComponent} from './examples/getting-started/getting-started-memory.component'; import {GroupsMemoryComponent} from './examples/groups/groups-memory.component'; import {ReactOnChangesMemoryComponent} from './examples/react-on-changes/react-on-changes-memory.component'; @@ -17,7 +18,8 @@ import {IntroductionRoutingModule} from './introduction.routing.module'; GettingStartedMemoryComponent, ReactOnChangesMemoryComponent, GroupsMemoryComponent, - AsyncPipeMemoryComponent + AsyncPipeMemoryComponent, + DragHandleComponent ], imports: [ CommonModule, diff --git a/projects/ng-sortgrid-demo/src/assets/gs7.png b/projects/ng-sortgrid-demo/src/assets/gs7.png new file mode 100644 index 0000000000000000000000000000000000000000..9ca09e0a5493f85d2d27d8dc2b0f10ccbe8ce0c3 GIT binary patch literal 25559 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 literal 0 HcmV?d00001 diff --git a/projects/ng-sortgrid/src/lib/ngsg-drag-handle.directive.spec.ts b/projects/ng-sortgrid/src/lib/ngsg-drag-handle.directive.spec.ts new file mode 100644 index 0000000..fb26409 --- /dev/null +++ b/projects/ng-sortgrid/src/lib/ngsg-drag-handle.directive.spec.ts @@ -0,0 +1,17 @@ +import { NgsgDragHandleDirective } from './ngsg-drag-handle.directive'; + +describe('NgsgDragHandleDirective', () => { + let sut: NgsgDragHandleDirective; + + const elementRef = { nativeElement: {} } as any; + + beforeEach(() => { + sut = new NgsgDragHandleDirective( + elementRef + ); + }); + + it('hould create an instance', () => { + expect(sut).toBeTruthy(); + }); +}); diff --git a/projects/ng-sortgrid/src/lib/ngsg-drag-handle.directive.ts b/projects/ng-sortgrid/src/lib/ngsg-drag-handle.directive.ts new file mode 100644 index 0000000..8265440 --- /dev/null +++ b/projects/ng-sortgrid/src/lib/ngsg-drag-handle.directive.ts @@ -0,0 +1,9 @@ +import { Directive, ElementRef } from '@angular/core'; + +@Directive({ + selector: '[ngSortgridDragHandle]' +}) +export class NgsgDragHandleDirective { + + constructor(public el: ElementRef){} +} diff --git a/projects/ng-sortgrid/src/lib/ngsg-item.directive.ts b/projects/ng-sortgrid/src/lib/ngsg-item.directive.ts index 96af658..e8965c7 100644 --- a/projects/ng-sortgrid/src/lib/ngsg-item.directive.ts +++ b/projects/ng-sortgrid/src/lib/ngsg-item.directive.ts @@ -1,5 +1,6 @@ import { AfterViewInit, + ContentChild, Directive, ElementRef, EventEmitter, @@ -23,6 +24,7 @@ import {NgsgReflectService} from './sort/reflection/ngsg-reflect.service'; import {NgsgSortService} from './sort/sort/ngsg-sort.service'; import {NgsgStoreService} from './store/ngsg-store.service'; import { NgsgClassService } from './helpers/class/ngsg-class.service'; +import { NgsgDragHandleDirective } from './ngsg-drag-handle.directive'; const selector = '[ngSortgridItem]'; @@ -37,6 +39,9 @@ export class NgsgItemDirective implements OnInit, OnChanges, AfterViewInit, OnDe @Output() sorted = new EventEmitter>(); + @ContentChild(NgsgDragHandleDirective) handle: NgsgDragHandleDirective; + + private handleElement: HTMLElement; private selected = false; private destroy$ = new Subject(); @@ -82,7 +87,14 @@ export class NgsgItemDirective implements OnInit, OnChanges, AfterViewInit, OnDe } ngAfterViewInit(): void { - this.el.nativeElement.draggable = true; + this.handleElement = this.handle?.el?.nativeElement || this.el.nativeElement; + + fromEvent(this.handleElement, 'mousedown').pipe( + takeUntil(this.destroy$) + ).subscribe(() => { + this.el.nativeElement.draggable = true; + } + ); } ngOnDestroy(): void { @@ -119,6 +131,7 @@ export class NgsgItemDirective implements OnInit, OnChanges, AfterViewInit, OnDe @HostListener('dragend') drop(): void { + this.el.nativeElement.draggable = false; if (!this.ngsgStore.hasSelectedItems(this.ngSortGridGroup)) { return; } diff --git a/projects/ng-sortgrid/src/lib/ngsg.module.ts b/projects/ng-sortgrid/src/lib/ngsg.module.ts index 6b93a55..6158a45 100644 --- a/projects/ng-sortgrid/src/lib/ngsg.module.ts +++ b/projects/ng-sortgrid/src/lib/ngsg.module.ts @@ -1,9 +1,10 @@ import { NgModule } from '@angular/core'; import { NgsgItemDirective } from './ngsg-item.directive'; +import { NgsgDragHandleDirective } from './ngsg-drag-handle.directive'; @NgModule({ - declarations: [NgsgItemDirective], - exports: [NgsgItemDirective] + declarations: [NgsgItemDirective, NgsgDragHandleDirective], + exports: [NgsgItemDirective, NgsgDragHandleDirective] }) export class NgsgModule {} From 947f4c0df5c0dacafbb528254cb60ab57119b647 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1?= Date: Wed, 13 Oct 2021 12:24:03 +0200 Subject: [PATCH 2/3] feat: (draghandle) typo fix --- projects/ng-sortgrid/src/lib/ngsg-drag-handle.directive.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/ng-sortgrid/src/lib/ngsg-drag-handle.directive.spec.ts b/projects/ng-sortgrid/src/lib/ngsg-drag-handle.directive.spec.ts index fb26409..d36eb44 100644 --- a/projects/ng-sortgrid/src/lib/ngsg-drag-handle.directive.spec.ts +++ b/projects/ng-sortgrid/src/lib/ngsg-drag-handle.directive.spec.ts @@ -11,7 +11,7 @@ describe('NgsgDragHandleDirective', () => { ); }); - it('hould create an instance', () => { + it('should create an instance', () => { expect(sut).toBeTruthy(); }); }); From 116f3f5fe02819df7823b86c2a91900429216d0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1?= Date: Wed, 13 Oct 2021 12:27:04 +0200 Subject: [PATCH 3/3] feat: (draghandle) fix failing test --- projects/ng-sortgrid/src/lib/ngsg-item.directive.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/ng-sortgrid/src/lib/ngsg-item.directive.spec.ts b/projects/ng-sortgrid/src/lib/ngsg-item.directive.spec.ts index 55b5667..493f93f 100644 --- a/projects/ng-sortgrid/src/lib/ngsg-item.directive.spec.ts +++ b/projects/ng-sortgrid/src/lib/ngsg-item.directive.spec.ts @@ -48,9 +48,9 @@ describe('NgsgItemDirective', () => { ); }); - it('should set the draggable attribute on the elment', () => { + it('should not set the draggable attribute on the elment', () => { sut.ngAfterViewInit(); - expect((elementRef.nativeElement as any).draggable).toBeTruthy(); + expect((elementRef.nativeElement as any).draggable).toBeFalsy(); }); it('should not set selectedElements if the event did not occur on the host', () => {