Skip to content

Commit a24b1ac

Browse files
crisbetommalerba
authored andcommitted
fix(cdk/drag-drop): handle not working when it has a child inside shadow DOM
Fixes that the children of the drag handle inside a shadow root weren't being detected. The problem was that we were using `_getEventTarget` to resolve the actual event target and using `contains` to verify that it's inside the handle. Since `contains` doesn't descend into shadow root, the call failed. These changes remove the `_getEventTarget` call since we can use the event `target` directly. Fixes #23680. (cherry picked from commit b9cda57)
1 parent a38fcc2 commit a24b1ac

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

src/cdk/drag-drop/directives/drag.spec.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1581,6 +1581,26 @@ describe('CdkDrag', () => {
15811581
flush();
15821582
}).toThrowError(/^cdkDragHandle must be attached to an element node/);
15831583
}));
1584+
1585+
it('should be able to drag an element using a handle with a shadow DOM child', fakeAsync(() => {
1586+
if (!_supportsShadowDom()) {
1587+
return;
1588+
}
1589+
1590+
const fixture = createComponent(
1591+
StandaloneDraggableWithShadowInsideHandle,
1592+
undefined,
1593+
undefined,
1594+
[ShadowWrapper],
1595+
);
1596+
fixture.detectChanges();
1597+
const dragElement = fixture.componentInstance.dragElement.nativeElement;
1598+
const handleChild = fixture.componentInstance.handleChild.nativeElement;
1599+
1600+
expect(dragElement.style.transform).toBeFalsy();
1601+
dragElementViaMouse(fixture, handleChild, 50, 100);
1602+
expect(dragElement.style.transform).toBe('translate3d(50px, 100px, 0px)');
1603+
}));
15841604
});
15851605

15861606
describe('in a drop container', () => {
@@ -6461,6 +6481,29 @@ class StandaloneDraggableWithIndirectHandle {
64616481
@ViewChild('handleElement') handleElement: ElementRef<HTMLElement>;
64626482
}
64636483

6484+
@Component({
6485+
selector: 'shadow-wrapper',
6486+
template: '<ng-content></ng-content>',
6487+
encapsulation: ViewEncapsulation.ShadowDom,
6488+
})
6489+
class ShadowWrapper {}
6490+
6491+
@Component({
6492+
template: `
6493+
<div #dragElement cdkDrag style="width: 100px; height: 100px; background: red;">
6494+
<div cdkDragHandle style="width: 10px; height: 10px;">
6495+
<shadow-wrapper>
6496+
<div #handleChild style="width: 10px; height: 10px; background: green;"></div>
6497+
</shadow-wrapper>
6498+
</div>
6499+
</div>
6500+
`,
6501+
})
6502+
class StandaloneDraggableWithShadowInsideHandle {
6503+
@ViewChild('dragElement') dragElement: ElementRef<HTMLElement>;
6504+
@ViewChild('handleChild') handleChild: ElementRef<HTMLElement>;
6505+
}
6506+
64646507
@Component({
64656508
encapsulation: ViewEncapsulation.None,
64666509
styles: [

src/cdk/drag-drop/drag-ref.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -628,8 +628,7 @@ export class DragRef<T = any> {
628628
// Delegate the event based on whether it started from a handle or the element itself.
629629
if (this._handles.length) {
630630
const targetHandle = this._handles.find(handle => {
631-
const target = _getEventTarget(event);
632-
return !!target && (target === handle || handle.contains(target as HTMLElement));
631+
return event.target && (event.target === handle || handle.contains(event.target as Node));
633632
});
634633

635634
if (targetHandle && !this._disabledHandles.has(targetHandle) && !this.disabled) {

0 commit comments

Comments
 (0)