Skip to content

Commit ecc96ec

Browse files
committed
feat(ghostElementTemplate): allow changing the ghost element contents
1 parent 74d9043 commit ecc96ec

File tree

2 files changed

+40
-3
lines changed

2 files changed

+40
-3
lines changed

src/draggable.directive.ts

+20-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ import {
1010
OnChanges,
1111
NgZone,
1212
SimpleChanges,
13-
Inject
13+
Inject,
14+
TemplateRef,
15+
ViewContainerRef
1416
} from '@angular/core';
1517
import { Subject, Observable, merge, ReplaySubject } from 'rxjs';
1618
import {
@@ -107,6 +109,11 @@ export class DraggableDirective implements OnInit, OnChanges, OnDestroy {
107109
*/
108110
@Input() ghostElementAppendTo: HTMLElement;
109111

112+
/**
113+
* An ng-template to be inserted into the parent element of the ghost element. It will overwrite any child nodes.
114+
*/
115+
@Input() ghostElementTemplate: TemplateRef<any>;
116+
110117
/**
111118
* Called when the element can be dragged along one axis and has the mouse or pointer device pressed on it
112119
*/
@@ -166,6 +173,7 @@ export class DraggableDirective implements OnInit, OnChanges, OnDestroy {
166173
private renderer: Renderer2,
167174
private draggableHelper: DraggableHelper,
168175
private zone: NgZone,
176+
private vcr: ViewContainerRef,
169177
@Inject(DOCUMENT) private document: any
170178
) {}
171179

@@ -296,6 +304,17 @@ export class DraggableDirective implements OnInit, OnChanges, OnDestroy {
296304
margin: '0'
297305
});
298306

307+
if (this.ghostElementTemplate) {
308+
const viewRef = this.vcr.createEmbeddedView(
309+
this.ghostElementTemplate
310+
);
311+
clone.innerHTML = '';
312+
clone.appendChild(viewRef.rootNodes[0]);
313+
dragEnded$.subscribe(() => {
314+
this.vcr.remove(this.vcr.indexOf(viewRef));
315+
});
316+
}
317+
299318
dragEnded$.subscribe(() => {
300319
clone.parentElement!.removeChild(clone);
301320
this.ghostElement = null;

test/draggable.directive.spec.ts

+20-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component, ElementRef, ViewChild } from '@angular/core';
1+
import { Component, ElementRef, TemplateRef, ViewChild } from '@angular/core';
22
import { TestBed, ComponentFixture } from '@angular/core/testing';
33
import { expect } from 'chai';
44
import * as sinon from 'sinon';
@@ -20,16 +20,21 @@ describe('draggable directive', () => {
2020
[dragCursor]="dragCursor"
2121
[dragActiveClass]="dragActiveClass"
2222
[ghostElementAppendTo]="ghostElementAppendTo"
23+
[ghostElementTemplate]="ghostElementTemplate"
2324
(dragPointerDown)="dragPointerDown($event)"
2425
(dragStart)="dragStart($event)"
2526
(dragging)="dragging($event)"
2627
(dragEnd)="dragEnd($event)">
2728
Drag me!
28-
</div>`
29+
</div>
30+
<ng-template #ghostElementTemplateRef><span>I'm being dragged!</span></ng-template>
31+
`
2932
})
3033
class TestComponent {
3134
@ViewChild(DraggableDirective) draggable: DraggableDirective;
3235
@ViewChild('draggableElement') draggableElement: ElementRef<HTMLDivElement>;
36+
@ViewChild('ghostElementTemplateRef')
37+
ghostElementTemplateRef: TemplateRef<any>;
3338
dragPointerDown = sinon.spy();
3439
dragStart = sinon.spy();
3540
dragging = sinon.spy();
@@ -42,6 +47,7 @@ describe('draggable directive', () => {
4247
dragCursor = 'move';
4348
dragActiveClass: string;
4449
ghostElementAppendTo: HTMLElement;
50+
ghostElementTemplate: TemplateRef<any>;
4551
}
4652

4753
beforeEach(() => {
@@ -697,4 +703,16 @@ describe('draggable directive', () => {
697703
'auto'
698704
);
699705
});
706+
707+
it('should use the contents of the ghost element template as the inner html of the ghost element', () => {
708+
fixture.componentInstance.ghostElementTemplate =
709+
fixture.componentInstance.ghostElementTemplateRef;
710+
fixture.detectChanges();
711+
const draggableElement =
712+
fixture.componentInstance.draggableElement.nativeElement;
713+
triggerDomEvent('mousedown', draggableElement, { clientX: 5, clientY: 10 });
714+
triggerDomEvent('mousemove', draggableElement, { clientX: 7, clientY: 10 });
715+
const ghostElement = draggableElement.nextSibling as HTMLElement;
716+
expect(ghostElement.innerHTML).to.equal("<span>I'm being dragged!</span>");
717+
});
700718
});

0 commit comments

Comments
 (0)