Skip to content

Commit

Permalink
feat(ghostElementTemplate): allow changing the ghost element contents
Browse files Browse the repository at this point in the history
  • Loading branch information
mattlewis92 committed Jun 27, 2018
1 parent 74d9043 commit ecc96ec
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 3 deletions.
21 changes: 20 additions & 1 deletion src/draggable.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import {
OnChanges,
NgZone,
SimpleChanges,
Inject
Inject,
TemplateRef,
ViewContainerRef
} from '@angular/core';
import { Subject, Observable, merge, ReplaySubject } from 'rxjs';
import {
Expand Down Expand Up @@ -107,6 +109,11 @@ export class DraggableDirective implements OnInit, OnChanges, OnDestroy {
*/
@Input() ghostElementAppendTo: HTMLElement;

/**
* An ng-template to be inserted into the parent element of the ghost element. It will overwrite any child nodes.
*/
@Input() ghostElementTemplate: TemplateRef<any>;

/**
* Called when the element can be dragged along one axis and has the mouse or pointer device pressed on it
*/
Expand Down Expand Up @@ -166,6 +173,7 @@ export class DraggableDirective implements OnInit, OnChanges, OnDestroy {
private renderer: Renderer2,
private draggableHelper: DraggableHelper,
private zone: NgZone,
private vcr: ViewContainerRef,
@Inject(DOCUMENT) private document: any
) {}

Expand Down Expand Up @@ -296,6 +304,17 @@ export class DraggableDirective implements OnInit, OnChanges, OnDestroy {
margin: '0'
});

if (this.ghostElementTemplate) {
const viewRef = this.vcr.createEmbeddedView(
this.ghostElementTemplate
);
clone.innerHTML = '';
clone.appendChild(viewRef.rootNodes[0]);
dragEnded$.subscribe(() => {
this.vcr.remove(this.vcr.indexOf(viewRef));
});
}

dragEnded$.subscribe(() => {
clone.parentElement!.removeChild(clone);
this.ghostElement = null;
Expand Down
22 changes: 20 additions & 2 deletions test/draggable.directive.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, ElementRef, ViewChild } from '@angular/core';
import { Component, ElementRef, TemplateRef, ViewChild } from '@angular/core';
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { expect } from 'chai';
import * as sinon from 'sinon';
Expand All @@ -20,16 +20,21 @@ describe('draggable directive', () => {
[dragCursor]="dragCursor"
[dragActiveClass]="dragActiveClass"
[ghostElementAppendTo]="ghostElementAppendTo"
[ghostElementTemplate]="ghostElementTemplate"
(dragPointerDown)="dragPointerDown($event)"
(dragStart)="dragStart($event)"
(dragging)="dragging($event)"
(dragEnd)="dragEnd($event)">
Drag me!
</div>`
</div>
<ng-template #ghostElementTemplateRef><span>I'm being dragged!</span></ng-template>
`
})
class TestComponent {
@ViewChild(DraggableDirective) draggable: DraggableDirective;
@ViewChild('draggableElement') draggableElement: ElementRef<HTMLDivElement>;
@ViewChild('ghostElementTemplateRef')
ghostElementTemplateRef: TemplateRef<any>;
dragPointerDown = sinon.spy();
dragStart = sinon.spy();
dragging = sinon.spy();
Expand All @@ -42,6 +47,7 @@ describe('draggable directive', () => {
dragCursor = 'move';
dragActiveClass: string;
ghostElementAppendTo: HTMLElement;
ghostElementTemplate: TemplateRef<any>;
}

beforeEach(() => {
Expand Down Expand Up @@ -697,4 +703,16 @@ describe('draggable directive', () => {
'auto'
);
});

it('should use the contents of the ghost element template as the inner html of the ghost element', () => {
fixture.componentInstance.ghostElementTemplate =
fixture.componentInstance.ghostElementTemplateRef;
fixture.detectChanges();
const draggableElement =
fixture.componentInstance.draggableElement.nativeElement;
triggerDomEvent('mousedown', draggableElement, { clientX: 5, clientY: 10 });
triggerDomEvent('mousemove', draggableElement, { clientX: 7, clientY: 10 });
const ghostElement = draggableElement.nextSibling as HTMLElement;
expect(ghostElement.innerHTML).to.equal("<span>I'm being dragged!</span>");
});
});

0 comments on commit ecc96ec

Please sign in to comment.