-
-
Notifications
You must be signed in to change notification settings - Fork 655
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How do I prevent draggable on input and btns #477
Comments
You can override the activator function of the sensors you're using to achieve this. If you return Something like: class MyPointerSensor extends PointerSensor {
static activators = [
{
eventName: 'onPointerDown',
handler: ({nativeEvent: event}) => {
if (
!event.isPrimary ||
event.button !== 0 ||
isInteractiveElement(event.target)
) {
return false;
}
return true;
},
},
];
}
function isInteractiveElement(element) {
const interactiveElements = [
'button',
'input',
'textarea',
'select',
'option',
];
if (interactiveElements.includes(element.tagName.toLowerCase())) {
return true;
}
return false;
} |
Thanks a lot!!!! Best solution. It would be better if we can achieve this by a prop config like "disableDragInteractiveElements" array By the way, I post the Typescript version if anyone need it import type { PointerEvent } from "react";
import { PointerSensor } from "@dnd-kit/core";
/**
* An extended "PointerSensor" that prevent some
* interactive html element(button, input, textarea, select, option...) from dragging
*/
export class SmartPointerSensor extends PointerSensor {
static activators = [
{
eventName: "onPointerDown" as any,
handler: ({ nativeEvent: event }: PointerEvent) => {
if (
!event.isPrimary ||
event.button !== 0 ||
isInteractiveElement(event.target as Element)
) {
return false;
}
return true;
},
},
];
}
function isInteractiveElement(element: Element | null) {
const interactiveElements = [
"button",
"input",
"textarea",
"select",
"option",
];
if (
element?.tagName &&
interactiveElements.includes(element.tagName.toLowerCase())
) {
return true;
}
return false;
} |
For someone who may have the same issue. Just add import type { MouseEvent, KeyboardEvent } from 'react'
import {
MouseSensor as LibMouseSensor,
KeyboardSensor as LibKeyboardSensor
} from '@dnd-kit/core'
export class MouseSensor extends LibMouseSensor {
static activators = [
{
eventName: 'onMouseDown' as const,
handler: ({ nativeEvent: event }: MouseEvent) => {
return shouldHandleEvent(event.target as HTMLElement)
}
}
]
}
export class KeyboardSensor extends LibKeyboardSensor {
static activators = [
{
eventName: 'onKeyDown' as const,
handler: ({ nativeEvent: event }: KeyboardEvent<Element>) => {
return shouldHandleEvent(event.target as HTMLElement)
}
}
]
}
function shouldHandleEvent(element: HTMLElement | null) {
let cur = element
while (cur) {
if (cur.dataset && cur.dataset.noDnd) {
return false
}
cur = cur.parentElement
}
return true
} |
This PR adds drag and drop functionality to the PropEditor-s rendered by the Studio, letting users reorder their components CustomMouseSensor was added so that drag and drop would not be activated inside input elements, otherwise it would not be possible to type inside them. see clauderic/dnd-kit#477 TEST=manual test when I add components a new component appears on the page, and also a new prop editor, and I can save the new component test that reordering works and can be saved to file, and also doesn't jitter or cause weird flashes as the PropEditor is dragged around (was an issue) test that I can type inside the PropEditor
when i use CustomMouseSensor, i got this error, how can i use CustomMouseSensor? here's my code: |
Thanks! This is improved TypeScript example: import { MouseSensor as LibMouseSensor, TouchSensor as LibTouchSensor } from '@dnd-kit/core';
import { MouseEvent, TouchEvent } from 'react';
// Block DnD event propagation if element have "data-no-dnd" attribute
const handler = ({ nativeEvent: event }: MouseEvent | TouchEvent) => {
let cur = event.target as HTMLElement;
while (cur) {
if (cur.dataset && cur.dataset.noDnd) {
return false;
}
cur = cur.parentElement as HTMLElement;
}
return true;
};
export class MouseSensor extends LibMouseSensor {
static activators = [{ eventName: 'onMouseDown', handler }] as typeof LibMouseSensor['activators'];
}
export class TouchSensor extends LibTouchSensor {
static activators = [{ eventName: 'onTouchStart', handler }] as typeof LibTouchSensor['activators'];
} |
【自动回复】已收到邮件。
|
Hello everyone, I tried this approach but for some reason my didnt work. |
【自动回复】已收到邮件。
|
【自动回复】已收到邮件。
|
I'm experiencing the same problem. |
【自动回复】已收到邮件。
|
This seems very fundamental, I think the proposed solution should either be added to the docs or built into the library behind a prop like "allowEventPropagation" that does it behind the scenes. |
Hi All, in Dnd kit library input tag onchage event not fired, I was tried above approach , I didn't get any luck. could please help me out this problem. Thank you in advance |
【自动回复】已收到邮件。
|
@DjVreditel your solution worked beautifully, thank you. Post this as when I saw the recent comments regarding solutions not working I lost some faith wondering if some recent updates caused changes, but I shouldn't. |
【自动回复】已收到邮件。
|
If you get "TypeError: Class constructor MouseSensor cannot be invoked without 'new'", patching the activators (since it's a static prop, can be done once) should work. Also canStartDrag can be anything you want. const FORBID_DRAG_ON = ["INPUT", "TEXTAREA"];
const canStartDrag = () => {
if (document.activeElement) {
const tagName = (document.activeElement as HTMLElement).tagName;
if (
FORBID_DRAG_ON.includes(tagName) ||
(tagName === "DIV" && (document.activeElement as HTMLDivElement).contentEditable === "true")
) {
return false;
}
}
return true;
};
const patchActivator = <T extends SensorOptions>(activators: Activators<T>, eventName: string): Activators<T> => {
const originalActivatorIndex = activators.findIndex((x) => x.eventName === eventName);
const originalActivator = activators[originalActivatorIndex];
activators[originalActivatorIndex] = {
eventName: originalActivator.eventName,
handler(...args) {
return canStartDrag() && originalActivator.handler(...args);
}
};
return activators;
};
patchActivator(KeyboardSensor.activators, "onKeyDown");
patchActivator(PointerSensor.activators, "onPointerDown"); |
【自动回复】已收到邮件。
|
More beautiful solution in my opinion, if you get import type { MouseEvent, TouchEvent } from 'react';
import { MouseSensor, TouchSensor } from '@dnd-kit/core';
const IGNORE_TAGS = ['BUTTON'];
// Block Dnd, if IGNORE_TAGS includes elements tag or element has data-no-dnd attribute
const customHandleEvent = (element: HTMLElement | null) => {
let cur = element;
while (cur) {
if (IGNORE_TAGS.includes(cur.tagName) || cur.dataset.noDnd) {
return false;
}
cur = cur.parentElement;
}
return true;
};
MouseSensor.activators = [
{
eventName: 'onMouseDown',
handler: ({ nativeEvent: event }: MouseEvent) => customHandleEvent(event.target as HTMLElement),
},
];
TouchSensor.activators = [
{
eventName: 'onTouchStart',
handler: ({ nativeEvent: event }: TouchEvent) => customHandleEvent(event.target as HTMLElement),
},
]; |
【自动回复】已收到邮件。
|
I have some operations btns and input inside the draggable area. I can't select text by moving mouse in input but triggering the drag event.
Although I can set "DelayConstraint" by sensors, but it's not a perfect solution while I need to balance the drag delay and operations in input.
I want to know is there a config for disable the part of "white" content from dragging but keep dragging on "red" area
The text was updated successfully, but these errors were encountered: