diff --git a/src/cdk/drag-drop/directives/drag.spec.ts b/src/cdk/drag-drop/directives/drag.spec.ts index e735ea1e5906..f3c8e5496f48 100644 --- a/src/cdk/drag-drop/directives/drag.spec.ts +++ b/src/cdk/drag-drop/directives/drag.spec.ts @@ -2978,6 +2978,21 @@ describe('CdkDrag', () => { expect(preview.textContent!.trim()).toContain('Hello One'); })); + it('should handle custom preview with multiple root nodes', fakeAsync(() => { + const fixture = createComponent(DraggableInDropZoneWithCustomMultiNodePreview); + fixture.detectChanges(); + const item = fixture.componentInstance.dragItems.toArray()[1].element.nativeElement; + + expect(() => { + startDraggingViaMouse(fixture, item); + }).not.toThrow(); + + const preview = document.querySelector('.cdk-drag-preview')! as HTMLElement; + + expect(preview).toBeTruthy(); + expect(preview.textContent!.trim()).toContain('HelloOne'); + })); + it('should be able to customize the placeholder', fakeAsync(() => { const fixture = createComponent(DraggableInDropZoneWithCustomPlaceholder); fixture.detectChanges(); @@ -3050,6 +3065,21 @@ describe('CdkDrag', () => { expect(placeholder.textContent!.trim()).toContain('Hello One'); })); + it('should handle custom placeholder with multiple root nodes', fakeAsync(() => { + const fixture = createComponent(DraggableInDropZoneWithCustomMultiNodePlaceholder); + fixture.detectChanges(); + const item = fixture.componentInstance.dragItems.toArray()[1].element.nativeElement; + + expect(() => { + startDraggingViaMouse(fixture, item); + }).not.toThrow(); + + const placeholder = document.querySelector('.cdk-drag-placeholder')! as HTMLElement; + + expect(placeholder).toBeTruthy(); + expect(placeholder.textContent!.trim()).toContain('HelloOne'); + })); + it('should clear the `transform` value from siblings when item is dropped`', fakeAsync(() => { const fixture = createComponent(DraggableInDropZone); fixture.detectChanges(); @@ -5192,6 +5222,28 @@ class DraggableInDropZoneWithCustomTextOnlyPreview { } +@Component({ + template: ` +
+
+ {{item}} + + Hello + {{item}} + +
+
+ ` +}) +class DraggableInDropZoneWithCustomMultiNodePreview { + @ViewChild(CdkDropList) dropInstance: CdkDropList; + @ViewChildren(CdkDrag) dragItems: QueryList; + items = ['Zero', 'One', 'Two', 'Three']; +} + @Component({ template: `
+
+ {{item}} + + Hello + {{item}} + +
+
+ ` +}) +class DraggableInDropZoneWithCustomMultiNodePlaceholder { + @ViewChildren(CdkDrag) dragItems: QueryList; + items = ['Zero', 'One', 'Two', 'Three']; +} + const CONNECTED_DROP_ZONES_STYLES = [` .cdk-drop-list { display: block; diff --git a/src/cdk/drag-drop/drag-ref.ts b/src/cdk/drag-drop/drag-ref.ts index 767ec9aaec20..c1a124b76949 100644 --- a/src/cdk/drag-drop/drag-ref.ts +++ b/src/cdk/drag-drop/drag-ref.ts @@ -1297,15 +1297,15 @@ function getPreviewInsertionPoint(documentRef: any): HTMLElement { * If the root is not an HTML element it gets wrapped in one. */ function getRootNode(viewRef: EmbeddedViewRef, _document: Document): HTMLElement { - const rootNode: Node = viewRef.rootNodes[0]; + const rootNodes: Node[] = viewRef.rootNodes; - if (rootNode.nodeType !== _document.ELEMENT_NODE) { - const wrapper = _document.createElement('div'); - wrapper.appendChild(rootNode); - return wrapper; + if (rootNodes.length === 1 && rootNodes[0].nodeType === _document.ELEMENT_NODE) { + return rootNodes[0] as HTMLElement; } - return rootNode as HTMLElement; + const wrapper = _document.createElement('div'); + rootNodes.forEach(node => wrapper.appendChild(node)); + return wrapper; } /**