From 751fe8a0b3cc433b53d7acf7ef23a9fc1c4dc1cf Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Fri, 22 Feb 2019 16:09:19 +0100 Subject: [PATCH] fix(drag-drop): clear duplicate ids from descendants (#15135) Fixes `CdkDrag` generating elements with duplicate ids, if one of its descendants has an id. Fixes #15120. --- src/cdk/drag-drop/directives/drag.spec.ts | 30 +++++++++++++++++++++++ src/cdk/drag-drop/drag-ref.ts | 7 ++++++ 2 files changed, 37 insertions(+) diff --git a/src/cdk/drag-drop/directives/drag.spec.ts b/src/cdk/drag-drop/directives/drag.spec.ts index 6a79930762b..6beb14b7f46 100644 --- a/src/cdk/drag-drop/directives/drag.spec.ts +++ b/src/cdk/drag-drop/directives/drag.spec.ts @@ -1392,6 +1392,21 @@ describe('CdkDrag', () => { expect(preview.getAttribute('id')).toBeFalsy(); })); + it('should clear the ids from descendants of the preview', fakeAsync(() => { + const fixture = createComponent(DraggableInDropZone); + fixture.detectChanges(); + const item = fixture.componentInstance.dragItems.toArray()[1].element.nativeElement; + const extraChild = document.createElement('div'); + extraChild.id = 'child-id'; + extraChild.classList.add('preview-child'); + item.appendChild(extraChild); + + startDraggingViaMouse(fixture, item); + + expect(document.querySelectorAll('.preview-child').length).toBeGreaterThan(1); + expect(document.querySelectorAll('[id="child-id"]').length).toBe(1); + })); + it('should not create a preview if the element was not dragged far enough', fakeAsync(() => { const fixture = createComponent(DraggableInDropZone, [], 5); fixture.detectChanges(); @@ -1597,6 +1612,21 @@ describe('CdkDrag', () => { expect(placeholder.getAttribute('id')).toBeFalsy(); })); + it('should clear the ids from descendants of the placeholder', fakeAsync(() => { + const fixture = createComponent(DraggableInDropZone); + fixture.detectChanges(); + const item = fixture.componentInstance.dragItems.toArray()[1].element.nativeElement; + const extraChild = document.createElement('div'); + extraChild.id = 'child-id'; + extraChild.classList.add('placeholder-child'); + item.appendChild(extraChild); + + startDraggingViaMouse(fixture, item); + + expect(document.querySelectorAll('.placeholder-child').length).toBeGreaterThan(1); + expect(document.querySelectorAll('[id="child-id"]').length).toBe(1); + })); + it('should not create placeholder if the element was not dragged far enough', fakeAsync(() => { const fixture = createComponent(DraggableInDropZone, [], 5); fixture.detectChanges(); diff --git a/src/cdk/drag-drop/drag-ref.ts b/src/cdk/drag-drop/drag-ref.ts index 50f79635b71..c67b3bfa9f1 100644 --- a/src/cdk/drag-drop/drag-ref.ts +++ b/src/cdk/drag-drop/drag-ref.ts @@ -1003,8 +1003,15 @@ function getTransform(x: number, y: number): string { /** Creates a deep clone of an element. */ function deepCloneNode(node: HTMLElement): HTMLElement { const clone = node.cloneNode(true) as HTMLElement; + const descendantsWithId = clone.querySelectorAll('[id]'); + // Remove the `id` to avoid having multiple elements with the same id on the page. clone.removeAttribute('id'); + + for (let i = 0; i < descendantsWithId.length; i++) { + descendantsWithId[i].removeAttribute('id'); + } + return clone; }